/*
*****************************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2002-2012, Advanced Audio Video Coding Standard, Part II
*
* DISCLAIMER OF WARRANTY
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations under
* the License.
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
* The AVS Working Group doesn't represent or warrant that the programs
* furnished here under are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy for standardization procedure is available at
* AVS Web site http://www.avs.org.cn. Patent Licensing is outside
* of AVS Working Group.
*
* The Initial Developer of the Original Code is Video subgroup of AVS
* Workinggroup.
* Contributors: Qin Yu,         Zhichu He,  Weiran Li,    Yong Ling,
*               Zhenjiang Shao, Jie Chen,   Junjun Si,    Xiaozhen Zheng, 
*               Jian Lou,       Qiang Wang, Jianwen Chen, Haiwu Zhao,
*               Guoping Li,     Siwei Ma,   Junhao Zheng, Zhiming Wang
*               Li Zhang,
******************************************************************************
*/


/*
*************************************************************************************
* File name: image.c
* Function: Decode a Slice
*
*************************************************************************************
*/


#include "../../lcommon/inc/contributors.h"

#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <sys/timeb.h>
#include <string.h>
#include <assert.h>
#ifdef WIN32
#include <IO.H>
#include <STDIO.H>
#endif

#include "global.h"
#include "../../lcommon/inc/commonVariables.h"
#include "header.h"
#include "annexb.h"
#include "../../lcommon/inc/memalloc.h"
#include "AEC.h"
#include "biaridecod.h"
#include "../../lcommon/inc/loop-filter.h"
#if ALF
#include "../../lcommon/inc/ComAdaptiveLoopFilter.h"
#include "../../ldecod/inc/DecAdaptiveLoopFilter.h"
void Copy_frame_for_ALF();
#endif
#if ROI_M3264
#include "pos_info.h"
#endif

// Adaptive frequency weighting quantization
#if FREQUENCY_WEIGHTING_QUANTIZATION
#include "wquant.h"
#endif

void DecideMvRange(); // rm52k

/* 08.16.2007--for user data after pic header */
unsigned char *temp_slice_buf;
int first_slice_length;
int first_slice_startpos;
/* 08.16.2007--for user data after pic header */
extern void readParaSAO_one_SMB(int smb_index,int mb_y, int mb_x, int smb_mb_height, int smb_mb_width, int *slice_sao_on, SAOBlkParam* saoBlkParam, SAOBlkParam* rec_saoBlkParam);
extern StatBits *StatBitsPtr;

#if MULTIVIEW_CODING
void addCurrMvtoBuf();
void delete_trbuffer();

extern multiView_depth_StatBits[MAX_VIEW];
extern multiView_StatBits[MAX_VIEW];
#endif

#if MULTIVIEW_CODING
int currPosInDPB;
#endif

/*
*************************************************************************
* Function:decodes one I- or P-frame
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

int decode_one_frame ( SNRParameters *snr )
{
  int current_header;
  int N8_SizeScale;

  time_t ltime1;                  // for time measurement
  time_t ltime2;

#ifdef WIN32
  struct _timeb tstruct1;
  struct _timeb tstruct2;
#else
  struct timeb tstruct1;
  struct timeb tstruct2;
#endif

  double framerate[8] = {24000.0 / 1001.0, 24.0, 25.0, 30000.0 / 1001.0, 30.0, 50.0, 60000.0 / 1001.0, 60.0}; 

#ifdef WIN32
  _ftime ( &tstruct1 );           // start time ms
#else
  ftime ( &tstruct1 );            // start time ms
#endif
  time ( &ltime1 );               // start time s

  img->current_mb_nr = -4711; // initialized to an impossible value for debugging -- correct value is taken from slice header

  current_header = Header();
  DecideMvRange();  //rm52k

  if ( current_header == EOS )
  {
    return EOS;
  }


  {
    N8_SizeScale = 1;

    if ( horizontal_size % ( MIN_CU_SIZE * N8_SizeScale ) != 0 )
    {
      img->auto_crop_right = ( MIN_CU_SIZE * N8_SizeScale ) - ( horizontal_size % ( MIN_CU_SIZE * N8_SizeScale ) );
    }
    else
    {
      img->auto_crop_right = 0;
    }
#if !INTERLACE_CODING
    if ( progressive_sequence )
#endif
    {
      if ( vertical_size % ( MIN_CU_SIZE * N8_SizeScale ) != 0 )
      {
        img->auto_crop_bottom = ( MIN_CU_SIZE * N8_SizeScale ) - ( vertical_size % ( MIN_CU_SIZE * N8_SizeScale ) );
      }
      else
      {
        img->auto_crop_bottom = 0;
      }
    }

    // Reinit parameters (NOTE: need to do before init_frame //
    img->width          = ( horizontal_size + img->auto_crop_right );
    img->height         = ( vertical_size + img->auto_crop_bottom );
    img->width_cr       = ( img->width >> 1 );

    if ( input->chroma_format == 1 )
    {
      img->height_cr      = ( img->height >> 1 );
    }

    img->PicWidthInMbs  = img->width / MIN_CU_SIZE;
    img->PicHeightInMbs = img->height / MIN_CU_SIZE;
    img->PicSizeInMbs   = img->PicWidthInMbs * img->PicHeightInMbs;
    img->max_mb_nr      = ( img->width * img->height ) / ( MIN_CU_SIZE * MIN_CU_SIZE );
  }

  if (img->new_sequence_flag && img->sequence_end_flag)
  {
	  end_SeqTr = img->tr;
	  img->sequence_end_flag = 0;
  }
  if( img->new_sequence_flag )
  {
	  next_IDRtr = img->tr;
	  next_IDRcoi = img->coding_order;
	  img->new_sequence_flag = 0;
  }
  // allocate memory for frame buffers
  if ( img->number == 0 )
  {
	  init_global_buffers ();
  }

#if MULTIVIEW_CODING
  if (img->number == 0 && img->view_index == 0 && img->bDepth == 0)
  {
	  Init_MultiView_Buffers();
  }
#endif

  img->current_mb_nr = 0;
  init_frame ();

  if ( img->picture_structure )
  {
    img->types = img->type;   // jlzheng 7.15

    if ( img->type != B_IMG )
    {
      pre_img_type  = img->type;
      pre_img_types = img->types;
    }

    picture_data ();

  }

#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
  if(img->typeb == BACKGROUND_IMG && background_picture_enable)
#else
  if(img->typeb == BACKGROUND_IMG && background_picture_enable && input->profile_id == 0x50)
#endif
  {
	  int l;
	  for(l=0; l<img->height; l++)
#if EXTEND_BD
		  memcpy(background_frame[0][l],imgY[l],img->width * sizeof(byte));
#else
          memcpy(background_frame[0][l],imgY[l],img->width);
#endif
	  for(l=0; l<img->height_cr; l++)
	  {
#if EXTEND_BD
		  memcpy(background_frame[1][l],imgUV[0][l],img->width_cr * sizeof(byte));
		  memcpy(background_frame[2][l],imgUV[1][l],img->width_cr * sizeof(byte));
#else
          memcpy(background_frame[1][l],imgUV[0][l],img->width_cr);
          memcpy(background_frame[2][l],imgUV[1][l],img->width_cr);
#endif
	  }
  }
#endif

#ifdef AVS2_S2_BGLONGTERM
  if(img->typeb == BACKGROUND_IMG && background_picture_output_flag == 0 )
	  background_number++;
#endif

#if MULTIVIEW_CODING
  if(img->view_index > 0 && img->type != I_IMG && img->type != B_IMG)
  {
	  int j, k;

	  for (j=0; j<REF_MAXBUFFER; j++)
	  {
		  ref[j] = currView_ref[j];
		  mvbuf[j] = currView_mvbuf[j];
		  refbuf[j] = currView_refbuf[j];

		  img->imgtr_fwRefDistance[j] = img->currView_imgtr_fwRefDistance[j];
		  img->imgcoi_ref[j] = img->currView_imgcoi_ref[j];

		  for (k=0; k<3; k++)
		  {
			  saorate[j][k]  	 = currView_saorate[j][k];
		  }

		  img->refered_by_others[j]  = img->currView_refered_by_others[j];
		  memcpy(ref_poc[j], currView_ref_poc[j], 4*sizeof(int));

	  }

  }
#endif

  if (img->type==B_IMG)
  {
	  img->imgtr_fwRefDistance[0] = trtmp;
  }

#if MULTIVIEW_CODING
  if (img->type==B_IMG)
  {		
	  img->currView_imgtr_fwRefDistance[0] = trtmp;
  }
#endif

  img->height = ( vertical_size + img->auto_crop_bottom );
  img->height_cr =  img->height / ( input->chroma_format == 1 ? 2 : 1 );
  img->PicWidthInMbs  = img->width / MIN_CU_SIZE;
  img->PicHeightInMbs = img->height / MIN_CU_SIZE;
  img->PicSizeInMbs   = img->PicWidthInMbs * img->PicHeightInMbs;


#ifdef WIN32
  _ftime ( &tstruct2 ); // end time ms
#else
  ftime ( &tstruct2 );  // end time ms
#endif

  time ( &ltime2 );                               // end time sec
  tmp_time = ( ltime2 * 1000 + tstruct2.millitm ) - ( ltime1 * 1000 + tstruct1.millitm );
  tot_time = tot_time + tmp_time;

  //rm52k_r2
  StatBitsPtr->curr_frame_bits = StatBitsPtr->curr_frame_bits * 8 + StatBitsPtr->emulate_bits - StatBitsPtr->last_unit_bits;
  StatBitsPtr->bitrate += StatBitsPtr->curr_frame_bits;
  StatBitsPtr->coded_pic_num++;

  if ( ( int ) ( StatBitsPtr->coded_pic_num - ( StatBitsPtr->time_s + 1 ) *framerate[frame_rate_code - 1] + 0.5 ) == 0 )
  {
    StatBitsPtr->total_bitrate[StatBitsPtr->time_s++] = StatBitsPtr->bitrate;
    StatBitsPtr->bitrate = 0;
  }

#if MULTIVIEW_CODING
  if(img->bDepth == 0)
  {
	  frame_postprocessing(snr);
  }
  else
  {
	  depth_frame_postprocessing(snr);
  }
#else
  frame_postprocessing();
#endif
  StatBitsPtr->curr_frame_bits = 0;
  StatBitsPtr->emulate_bits    = 0;
  StatBitsPtr->last_unit_bits  = 0;

  //! TO 19.11.2001 Known Problem: for init_frame we have to know the picture type of the actual frame
  //! in case the first slice of the P-Frame following the I-Frame was lost we decode this P-Frame but//! do not write it because it was assumed to be an I-Frame in init_frame.So we force the decoder to
  //! guess the right picture type. This is a hack a should be removed by the time there is a clean
  //! solution where we do not have to know the picture type for the function init_frame.
  //! End TO 19.11.2001//Lou
#if MULTIVIEW_CODING
  if (img->view_index == 0 && img->bDepth == 0)
  {
#endif
#if DHP
	if ( img->type == I_IMG || img->type == P_IMG || img->type == F_IMG ) 
#else
	if ( img->type == I_IMG || img->type == P_IMG ) // I or P pictures
#endif
	{
		img->number++;
	}
	else
	{
		Bframe_ctr++;  // B pictures
	}
#if MULTIVIEW_CODING
  }
#endif

  return ( SOP );
}

/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
#if MULTIVIEW_CODING
void report_frame ( outdata data, int pos )
{
	FILE *file;
	char *Frmfld;
	char Frm[] = "FRM";
	char Fld[] = "FLD";
	file = fopen ( "stat.dat", "at" );
	if (data.stdoutdata[img->view_index][pos].picture_structure)
	{
		Frmfld = Frm;
	}
	else
	{
		Frmfld = Fld;
	}
#if INTERLACE_CODING  
	if (img->is_field_sequence)   //rcs??
	{
		Frmfld = Fld;
	}
#endif
	if ( data.stdoutdata[img->view_index][pos].tr == end_SeqTr ) // I picture
	{
		//if ( img->new_sequence_flag == 1 )
		{
			img->sequence_end_flag = 0;
			fprintf ( stdout, "Sequence End\n\n" );
		}
	}
	if ( data.stdoutdata[img->view_index][pos].tr == next_IDRtr )
	{
		if ( vec_flag )
		{
			vec_flag = 0;
			fprintf ( stdout, "Video Edit Code\n" );
		}
		fprintf ( stdout, "Sequence Header\n" );
	}

	if ( data.stdoutdata[img->view_index][pos].type == I_IMG ) // I picture
	{
#ifdef AVS2_S2_BGLONGTERM
		if(data.stdoutdata[img->view_index][pos].typeb == BACKGROUND_IMG && input->profile_id == 0x50)
		{
			if(background_picture_output_flag)
			{
				printf ( "%3d(G)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
					data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.stdoutdata[img->view_index][pos].curr_frame_bits, data.stdoutdata[img->view_index][pos].emulate_bits );

				fprintf ( file, "%3d(G)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
					data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
			}
			else
			{
				printf ( "%3d(GB) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
					data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.stdoutdata[img->view_index][pos].curr_frame_bits, data.stdoutdata[img->view_index][pos].emulate_bits );

				fprintf ( file, "%3d(GB) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
					data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
			}
		}
		else
		{
			printf ( "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
				data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.stdoutdata[img->view_index][pos].curr_frame_bits, data.stdoutdata[img->view_index][pos].emulate_bits );

			fprintf ( file, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
				data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
		}
#else
		printf ( "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[img->view_index][pos].framenum, data.stdoutdata[img->view_index][pos].tr, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.stdoutdata[img->view_index][pos].curr_frame_bits, data.stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[img->view_index][pos].framenum, data.stdoutdata[img->view_index][pos].tr, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
#endif
	}

#ifdef AVS2_S2_S
	else if ( data.stdoutdata[img->view_index][pos].type == P_IMG && data.stdoutdata[img->view_index][pos].typeb != BP_IMG)
#else
	else if ( data.stdoutdata[img->view_index][pos].type ==P_IMG ) // P pictures
#endif
	{
		printf ( "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.stdoutdata[img->view_index][pos].curr_frame_bits, data.stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
	}
#ifdef AVS2_S2_S
	else if ( data.stdoutdata[img->view_index][pos].type == P_IMG && data.stdoutdata[img->view_index][pos].typeb == BP_IMG)
	{
		printf ( "%3d(S)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.stdoutdata[img->view_index][pos].curr_frame_bits, data.stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(S)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
	}
#endif
#if DHP
	else if ( data.stdoutdata[img->view_index][pos].type ==F_IMG ) // F pictures
	{
		printf ( "%3d(F)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.stdoutdata[img->view_index][pos].curr_frame_bits, data.stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(F)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
	}
#endif 
	else // B pictures
	{
		printf ( "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.stdoutdata[img->view_index][pos].curr_frame_bits, data.stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].tr+total_frames*256, data.stdoutdata[img->view_index][pos].qp, data.stdoutdata[img->view_index][pos].snr_y, data.stdoutdata[img->view_index][pos].snr_u, data.stdoutdata[img->view_index][pos].snr_v, data.stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
	}

	fclose ( file );
	fflush ( stdout );
	FrameNum++;
}
#else
void report_frame ( outdata data, int pos )
{
	FILE *file;
  char *Frmfld;
  char Frm[] = "FRM";
  char Fld[] = "FLD";
	file = fopen ( "stat.dat", "at" );
  if (data.stdoutdata[pos].picture_structure)
  {
    Frmfld = Frm;
  }
  else
  {
    Frmfld = Fld;
  }
#if INTERLACE_CODING  
  if (img->is_field_sequence)   //rcs??
  {
    Frmfld = Fld;
  }
#endif
#if REF_MINUS
  if ( (data.stdoutdata[pos].tr + total_frames*256) == end_SeqTr ) // I picture
#else
	if ( data.stdoutdata[pos].tr == end_SeqTr ) // I picture
#endif
	{
		//if ( img->new_sequence_flag == 1 )
		{
			img->sequence_end_flag = 0;
			fprintf ( stdout, "Sequence End\n\n" );
		}
	}
#if REF_MINUS
	if ( (data.stdoutdata[pos].tr + total_frames*256) == next_IDRtr )
#else
	if ( data.stdoutdata[pos].tr == next_IDRtr )
#endif
	{
		if ( vec_flag )
		{
			vec_flag = 0;
			fprintf ( stdout, "Video Edit Code\n" );
		}
		fprintf ( stdout, "Sequence Header\n" );
	}

	if ( data.stdoutdata[pos].type == I_IMG ) // I picture
	{
#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
		if(data.stdoutdata[pos].typeb == BACKGROUND_IMG)
#else
		if(data.stdoutdata[pos].typeb == BACKGROUND_IMG && input->profile_id == 0x50)
#endif
		{
			if(background_picture_output_flag)
			{
#if REF_MINUS
				printf ( "%3d(G)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
					data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

				fprintf ( file, "%3d(G)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
					data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#else
				printf ( "%3d(G)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
					data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

				fprintf ( file, "%3d(G)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
					data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#endif
			}
			else
			{
#if REF_MINUS
				printf ( "%3d(GB) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
					data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

				fprintf ( file, "%3d(GB) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
					data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#else
				printf ( "%3d(GB) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
					data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

				fprintf ( file, "%3d(GB) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
					data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#endif
			}
		}
		else
		{
#if REF_MINUS
			printf ( "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
				data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

			fprintf ( file, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
				data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#else
			printf ( "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
				data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

			fprintf ( file, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
				data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#endif
		}
#else
		printf ( "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#endif
	}

#ifdef AVS2_S2_S
	else if ( data.stdoutdata[pos].type == P_IMG && data.stdoutdata[pos].typeb != BP_IMG)
#else
	else if ( data.stdoutdata[pos].type ==P_IMG ) // P pictures
#endif
	{
#if REF_MINUS
		printf ( "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#else
		printf ( "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].tr, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#endif
	}
#ifdef AVS2_S2_S
	else if ( data.stdoutdata[pos].type == P_IMG && data.stdoutdata[pos].typeb == BP_IMG)
	{
#if REF_MINUS
		printf ( "%3d(S)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(S)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); 
#else
		printf ( "%3d(S)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(S)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].tr, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#endif
	}
#endif
#if DHP
	else if ( data.stdoutdata[pos].type ==F_IMG ) // F pictures
	{
#if REF_MINUS
		printf ( "%3d(F)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(F)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#else
		printf ( "%3d(F)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(F)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].tr, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#endif
	}
#endif 
	else // B pictures
	{
#if REF_MINUS
		printf ( "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].tr+total_frames*256, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#else
		printf ( "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.stdoutdata[pos].framenum, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld, data.stdoutdata[pos].curr_frame_bits, data.stdoutdata[pos].emulate_bits );

		fprintf ( file, "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.stdoutdata[pos].tr, data.stdoutdata[pos].tr, data.stdoutdata[pos].qp, data.stdoutdata[pos].snr_y, data.stdoutdata[pos].snr_u, data.stdoutdata[pos].snr_v, data.stdoutdata[pos].tmp_time, Frmfld ); //20080721
#endif
	}

	fclose ( file );
	fflush ( stdout );
	FrameNum++;
}
#endif
/*
*************************************************************************
* Function:Find PSNR for all three components.Compare decoded frame with
the original sequence. Read input->jumpd frames to reflect frame skipping.
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
#ifdef WIN32
void find_snr (SNRParameters *snr, int p_ref )
#else
void find_snr (SNRParameters *snr, FILE *p_ref )          //!< filestream to reference YUV file
#endif
{
  int i, j;
#if EXTEND_BD
#ifdef WIN32
  __int64 diff_y, diff_u, diff_v;
#else
  int64_t diff_y, diff_u, diff_v;
#endif
#else
  int diff_y, diff_u, diff_v;
#endif
  int uv;
  int uvformat = input->chroma_format == 1 ? 4 : 2;

#if EXTEND_BD
  int nOutputSampleSize = (input->output_bit_depth > 8) ? 2 : 1;
  unsigned char chTemp[2];
  int nBitDepthDiff = input->sample_bit_depth - input->output_bit_depth; // assume coding bit depth no less than output bit depth
#endif

#ifdef WIN32
  __int64 status;
#else
  int  status;
#endif

  int img_width = ( img->width - img->auto_crop_right );
  int img_height = ( img->height - img->auto_crop_bottom );
  int img_width_cr = ( img_width / 2 );
  int img_height_cr = ( img_height / ( input->chroma_format == 1 ? 2 : 1 ) );
#ifdef WIN32
  const unsigned int  bytes_y = img_width * img_height;
  const unsigned int  bytes_uv = img_width_cr * img_height_cr;
  const __int64 framesize_in_bytes = ( __int64 ) ( bytes_y + 2 * bytes_uv );
#else
  const unsigned int  bytes_y = img_width * img_height;
  const unsigned int  bytes_uv = img_width_cr * img_height_cr;
  const int64_t framesize_in_bytes = bytes_y + 2 * bytes_uv;
#endif

  unsigned char *buf;

  int   offset_units;

  if ( !input->yuv_structure )
  {
#if EXTEND_BD
    buf = malloc ( nOutputSampleSize * bytes_y );
#else
    buf = malloc ( bytes_y );
#endif
  }
  else
  {
#if EXTEND_BD
    buf = malloc ( nOutputSampleSize * (bytes_y + 2 * bytes_uv) );
#else
    buf = malloc ( bytes_y + 2 * bytes_uv );
#endif
  }

  if ( NULL == buf )
  {
    no_mem_exit ( "find_snr: buf" );
  }

  snr->snr_y = 0.0;
  snr->snr_u = 0.0;
  snr->snr_v = 0.0;

#ifndef WIN32
  rewind ( p_ref );
#endif

  if ( RefPicExist )
  {
#ifdef WIN32

    if ( !input->ref_pic_order ) //ref order
    {
#if EXTEND_BD
#if REF_MINUS
      status = _lseeki64 ( p_ref, nOutputSampleSize * framesize_in_bytes * (img->tr+total_frames*256), SEEK_SET );
#else
      status = _lseeki64 ( p_ref, nOutputSampleSize * framesize_in_bytes * img->tr , SEEK_SET );
#endif
#else
      status = _lseeki64 ( p_ref, framesize_in_bytes * img->tr , SEEK_SET );
#endif
    }
    else
    {
#if EXTEND_BD
      status = _lseeki64 ( p_ref, nOutputSampleSize * framesize_in_bytes * dec_ref_num, SEEK_SET );
#else
      status = _lseeki64 ( p_ref, framesize_in_bytes * dec_ref_num, SEEK_SET );
#endif
    }

#else

    if ( !input->ref_pic_order ) //ref order
    {
#if EXTEND_BD
#if REF_MINUS
	  status = fseeko ( p_ref, (off_t)(nOutputSampleSize * framesize_in_bytes * (img->tr+total_frames*256)/*( img->type == B_IMG ? img->tr : FrameNum )*/), 0 );
#else
      status = fseeko ( p_ref, (off_t)(nOutputSampleSize * framesize_in_bytes * img->tr/*( img->type == B_IMG ? img->tr : FrameNum )*/), 0 );
#endif
#else
      status = fseek ( p_ref, framesize_in_bytes * img->tr/*( img->type == B_IMG ? img->tr : FrameNum )*/, 0 );
#endif
    }
    else
    {
#if EXTEND_BD
      status = fseeko ( p_ref, (off_t)(nOutputSampleSize * framesize_in_bytes * dec_ref_num), 0 );
#else
      status = fseek ( p_ref, framesize_in_bytes * dec_ref_num, 0 );
#endif
    }

#endif

#ifdef WIN32

    if ( status == -1 )
#else
    if ( status != 0 )
#endif
    {
      snprintf ( errortext, ET_SIZE, "Error in seeking img->tr: %d", img->tr );
      RefPicExist = 0;
    }
  }

#ifdef WIN32

  if ( !input->yuv_structure )
  {
#if EXTEND_BD
    _read ( p_ref, buf, nOutputSampleSize * bytes_y );
#else
    _read ( p_ref, buf, bytes_y );
#endif
  }
  else
  {
#if EXTEND_BD
    _read ( p_ref, buf, nOutputSampleSize * (bytes_y + 2 * bytes_uv) );
#else
    _read ( p_ref, buf, bytes_y + 2 * bytes_uv );
#endif
  }

  if ( !input->yuv_structure ) //YUV
  {
    for ( j = 0; j < img_height; j++ )
    {
#if EXTEND_BD
      if (input->output_bit_depth == 8)
      {
        for ( i = 0; i < img_width; i++)
        {
          imgYRef[j][i] = buf[j * img_width + i];
          imgYRef[j][i] &= 0xff; // reset high 8 bits
        }
      }
      else if (input->output_bit_depth == 10)
      {
        for ( i = 0; i < img_width; i++)
        {
          imgYRef[j][i] = ((byte *)buf)[j * img_width + i] & 0x3ff;
        }
      }
      else if (input->output_bit_depth == 12)
      {
        for ( i = 0; i < img_width; i++)
        {
          imgYRef[j][i] = ((byte *)buf)[j * img_width + i] & 0xfff;
        }
      }

#else
      memcpy ( &imgYRef[j][0], buf + j * img_width, img_width );
#endif
    }
  }
  else  //U0Y0 V1Y1
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
#if EXTEND_BD
        if (input->output_bit_depth == 8)
        {
          offset_units = j * img_width + i;
          imgYRef[j][i] = buf[2 * offset_units + 1];
          imgYRef[j][i] &= 0xff;
          if ( offset_units % 2 == 0 ) //U component
          {
            imgUVRef[0][j][i / 2] = buf[2 * offset_units];
          }
          else                  //V component
          {
            imgUVRef[1][j][i / 2] = buf[2 * offset_units];
          }
        }
        else if (input->output_bit_depth == 10)
        {
          offset_units = j * img_width + i;
          imgYRef[j][i] = ((byte *)buf)[2 * offset_units + 1];
          imgYRef[j][i] = imgYRef[j][i] & 0x3ff;
          if ( offset_units % 2 == 0 ) //U component
          {
            imgUVRef[0][j][i / 2] = ((byte *)buf)[2 * offset_units];
            imgUVRef[0][j][i / 2] &= 0x3ff;
          }
          else                  //V component
          {
            imgUVRef[1][j][i / 2] = ((byte *)buf)[2 * offset_units];
            imgUVRef[1][j][i / 2] &= 0x3ff;
          }
        }
        else if (input->output_bit_depth == 12)
        {
          offset_units = j * img_width + i;
          imgYRef[j][i] = ((byte *)buf)[2 * offset_units + 1];
          imgYRef[j][i] = imgYRef[j][i] & 0xfff;
          if ( offset_units % 2 == 0 ) //U component
          {
            imgUVRef[0][j][i / 2] = ((byte *)buf)[2 * offset_units];
            imgUVRef[0][j][i / 2] &= 0xfff;
          }
          else                  //V component
          {
            imgUVRef[1][j][i / 2] = ((byte *)buf)[2 * offset_units];
            imgUVRef[1][j][i / 2] &= 0xfff;
          }
        }

#else
        offset_units = j * img_width + i;
        imgYRef[j][i] = buf[2 * offset_units + 1];

        if ( offset_units % 2 == 0 ) //U component
        {
          imgUVRef[0][j][i / 2] = buf[2 * offset_units];
        }
        else                  //V component
        {
          imgUVRef[1][j][i / 2] = buf[2 * offset_units];
        }
#endif
      }
    }
  }

#else
#if EXTEND_BD
  if ( !input->yuv_structure )
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        if (input->output_bit_depth == 8)
        {
          chTemp[0] = fgetc( p_ref );
          imgYRef[j][i] = chTemp[0];
        }
        else if (input->output_bit_depth == 10)
        {
          chTemp[0] = fgetc( p_ref );
          chTemp[1] = fgetc( p_ref );
          imgYRef[j][i] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
        }
        else if (input->output_bit_depth == 12)
        {
          chTemp[0] = fgetc( p_ref );
          chTemp[1] = fgetc( p_ref );
          imgYRef[j][i] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
        }
      }
    }
  }
  else
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        if (input->output_bit_depth == 8)
        {
          offset_units = j * img_width + i;
          if ( offset_units % 2 == 0 ) //U component
          {
            imgUVRef[0][j][i / 2] = fgetc ( p_ref );
          }
          else          //V component
          {
            imgUVRef[1][j][i / 2] = fgetc ( p_ref );
          }

          imgYRef[j][i] = fgetc ( p_ref );
        }
        else if (input->output_bit_depth == 10)
        {
          offset_units = j * img_width + i;
          if ( offset_units % 2 == 0 ) //U component
          {
            chTemp[0] = fgetc( p_ref );
            chTemp[1] = fgetc( p_ref );
            imgUVRef[0][j][i / 2] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
          }
          else          //V component
          {
            chTemp[0] = fgetc( p_ref );
            chTemp[1] = fgetc( p_ref );
            imgUVRef[1][j][i / 2] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
          }
          chTemp[0] = fgetc( p_ref );
          chTemp[1] = fgetc( p_ref );
          imgYRef[j][i] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
        }
        else if (input->output_bit_depth == 12)
        {
          offset_units = j * img_width + i;
          if ( offset_units % 2 == 0 ) //U component
          {
            chTemp[0] = fgetc( p_ref );
            chTemp[1] = fgetc( p_ref );
            imgUVRef[0][j][i / 2] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
          }
          else          //V component
          {
            chTemp[0] = fgetc( p_ref );
            chTemp[1] = fgetc( p_ref );
            imgUVRef[1][j][i / 2] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
          }
          chTemp[0] = fgetc( p_ref );
          chTemp[1] = fgetc( p_ref );
          imgYRef[j][i] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
        }
      }
    }
  }
#else
  if ( !input->yuv_structure )
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        imgYRef[j][i] = fgetc ( p_ref );
      }
    }
  }
  else
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        offset_units = j * img_width + i;

        if ( offset_units % 2 == 0 ) //U component
        {
          imgUVRef[0][j][i / 2] = fgetc ( p_ref );
        }
        else          //V component
        {
          imgUVRef[1][j][i / 2] = fgetc ( p_ref );
        }

        imgYRef[j][i] = fgetc ( p_ref );
      }
    }
  }
#endif
#endif

  for ( uv = 0; uv < 2; uv++ )
  {
    if ( !input->yuv_structure )
    {
#ifdef WIN32
#if EXTEND_BD
      _read ( p_ref, buf, nOutputSampleSize * img_height_cr * img_width_cr );
#else
      _read ( p_ref, buf, img_height_cr * img_width_cr );
#endif

      for ( j = 0; j < img_height_cr; j++ )
      {
#if EXTEND_BD
        for ( i = 0; i < img_width_cr; i++)
        {
          if (input->output_bit_depth == 8)
          {            
            imgUVRef[uv][j][i] = buf[j * img_width_cr + i];
            imgUVRef[uv][j][i] &= 0xff;
          }
          else if (input->output_bit_depth == 10)
          {
            imgUVRef[uv][j][i] = ((byte *)buf)[j * img_width_cr + i] & 0x3ff;
          }
          else if (input->output_bit_depth == 12)
          {
            imgUVRef[uv][j][i] = ((byte *)buf)[j * img_width_cr + i] & 0xfff;
          }
        }
#else
        memcpy ( &imgUVRef[uv][j][0], buf + j * img_width_cr, img_width_cr );
#endif
      }

#else

      for ( j = 0; j < img_height_cr; j++ )
      {
        for ( i = 0; i < img_width_cr; i++ )
        {
#if EXTEND_BD
          if (input->output_bit_depth == 8)
          {
            imgUVRef[uv][j][i] = fgetc ( p_ref );
          }
          else if (input->output_bit_depth == 10)
          {
            chTemp[0] = fgetc ( p_ref );
            chTemp[1] = fgetc ( p_ref );
            imgUVRef[uv][j][i] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
          }
          else if (input->output_bit_depth == 12)
          {
            chTemp[0] = fgetc ( p_ref );
            chTemp[1] = fgetc ( p_ref );
            imgUVRef[uv][j][i] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
          }
#else
          imgUVRef[uv][j][i] = fgetc ( p_ref );
#endif
        }
      }

#endif
    }
  }

  img->quad[0] = 0;
  diff_y = 0;

  for ( j = 0; j < img_height; ++j )
  {
    for ( i = 0; i < img_width; ++i )
    {
#if EXTEND_BD
      if (nBitDepthDiff == 0)
      {
        diff_y += img->quad[abs ( imgY[j][i] - imgYRef[j][i] ) ];
      }
      else if (nBitDepthDiff > 0)
      {
        diff_y += img->quad[abs ( Clip1((imgY[j][i] + (1 << (nBitDepthDiff - 1))) >> nBitDepthDiff)  - imgYRef[j][i] ) ];
      }

#else
      diff_y += img->quad[abs ( imgY[j][i] - imgYRef[j][i] ) ];
#endif
    }
  }

  // Chroma
  diff_u = 0;
  diff_v = 0;

  for ( j = 0; j < img_height_cr; ++j )
  {
    for ( i = 0; i < img_width_cr; ++i )
    {
#if EXTEND_BD
      if (nBitDepthDiff == 0)
      {
        diff_u += img->quad[abs ( imgUVRef[0][j][i] - imgUV[0][j][i] ) ];
        diff_v += img->quad[abs ( imgUVRef[1][j][i] - imgUV[1][j][i] ) ];
      }
      else if (nBitDepthDiff > 0)
      {
        diff_u += img->quad[abs ( imgUVRef[0][j][i] - Clip1((imgUV[0][j][i] + (1 << (nBitDepthDiff - 1))) >> nBitDepthDiff) ) ];
        diff_v += img->quad[abs ( imgUVRef[1][j][i] - Clip1((imgUV[1][j][i] + (1 << (nBitDepthDiff - 1))) >> nBitDepthDiff) ) ];
      }
#else
      diff_u += img->quad[abs ( imgUVRef[0][j][i] - imgUV[0][j][i] ) ];
      diff_v += img->quad[abs ( imgUVRef[1][j][i] - imgUV[1][j][i] ) ];
#endif
    }
  }

  // Collecting SNR statistics
  if ( diff_y != 0 )
  {
#if EXTEND_BD
    snr->snr_y = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) );  // luma snr for current frame
#else
    snr->snr_y = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) );  // luma snr for current frame
#endif
  }

  if ( diff_u != 0 )
  {
#if EXTEND_BD
    snr->snr_u = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) );  //  chroma snr for current frame,422
#else
    snr->snr_u = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) );  //  chroma snr for current frame,422
#endif
  }

  if ( diff_v != 0 )
  {
#if EXTEND_BD
    snr->snr_v = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) );  //  chroma snr for current frame,422
#else
    snr->snr_v = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) );  //  chroma snr for current frame,422
#endif
  }

  if ( img->number == /*0*/1 ) // first
  {
#if EXTEND_BD
    snr->snr_y1 = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) ); // keep luma snr for first frame
    snr->snr_u1 = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) ); // keep chroma snr for first frame,422
    snr->snr_v1 = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) ); // keep chroma snr for first frame,422
#else
    snr->snr_y1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) ); // keep luma snr for first frame
    snr->snr_u1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) ); // keep chroma snr for first frame,422
    snr->snr_v1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) ); // keep chroma snr for first frame,422
#endif
    snr->snr_ya = snr->snr_y1;
    snr->snr_ua = snr->snr_u1;
    snr->snr_va = snr->snr_v1;

    if ( diff_y == 0 )
    {
      snr->snr_ya =/*50*/0;
    }

    if ( diff_u == 0 )
    {
      snr->snr_ua =/*50*/0;
    }

    if ( diff_v == 0 )
    {
      snr->snr_va =/*50*/0;
    }
  }
  else
  {
    snr->snr_ya = ( float ) ( snr->snr_ya * ( img->number + Bframe_ctr - 1 ) + snr->snr_y ) / ( img->number + Bframe_ctr ); // average snr chroma for all frames 20080721
    snr->snr_ua = ( float ) ( snr->snr_ua * ( img->number + Bframe_ctr - 1 ) + snr->snr_u ) / ( img->number + Bframe_ctr ); // average snr luma for all frames 20080721
    snr->snr_va = ( float ) ( snr->snr_va * ( img->number + Bframe_ctr - 1 ) + snr->snr_v ) / ( img->number + Bframe_ctr ); // average snr luma for all frames 20080721
  }

  free ( buf );
}

#if AVS2_SCENE_CD
/*
*************************************************************************
* Function:Find PSNR for BACKGROUND PICTURE.Compare decoded frame with
the original sequence. Read input->jumpd frames to reflect frame skipping.
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
#ifdef WIN32
void find_snr_background (SNRParameters *snr, int p_ref )
#else
void find_snr_background (SNRParameters *snr, FILE *p_ref )          //!< filestream to reference YUV file
#endif
{
  int i, j;
#if EXTEND_BD
#ifdef WIN32
  __int64 diff_y, diff_u, diff_v;
#else
  int64_t diff_y, diff_u, diff_v;
#endif
#else
  int diff_y, diff_u, diff_v;
#endif
  int uv;
  int uvformat = input->chroma_format == 1 ? 4 : 2;

#if EXTEND_BD
  int nOutputSampleSize = (input->output_bit_depth > 8) ? 2 : 1;
  unsigned char chTemp[2];
  int nBitDepthDiff = input->sample_bit_depth - input->output_bit_depth; // assume coding bit depth no less than output bit depth
#endif

#ifdef WIN32
  __int64 status;
#else
  int  status;
#endif

  int img_width = ( img->width - img->auto_crop_right );
  int img_height = ( img->height - img->auto_crop_bottom );
  int img_width_cr = ( img_width / 2 );
  int img_height_cr = ( img_height / ( input->chroma_format == 1 ? 2 : 1 ) );
#ifdef WIN32
  const unsigned int  bytes_y = img_width * img_height;
  const unsigned int  bytes_uv = img_width_cr * img_height_cr;
  const __int64 framesize_in_bytes = ( __int64 ) ( bytes_y + 2 * bytes_uv );
#else
  const unsigned int  bytes_y = img_width * img_height;
  const unsigned int  bytes_uv = img_width_cr * img_height_cr;
  const int64_t framesize_in_bytes = bytes_y + 2 * bytes_uv;
#endif

  unsigned char *buf;

  int   offset_units;

  if ( !input->yuv_structure )
  {
#if EXTEND_BD
    buf = malloc ( nOutputSampleSize * bytes_y );
#else
    buf = malloc ( bytes_y );
#endif
  }
  else
  {
#if EXTEND_BD
    buf = malloc ( nOutputSampleSize * (bytes_y + 2 * bytes_uv) );
#else
    buf = malloc ( bytes_y + 2 * bytes_uv );
#endif
  }

  if ( NULL == buf )
  {
    no_mem_exit ( "find_snr_background: buf" );
  }

  snr->snr_y = 0.0;
  snr->snr_u = 0.0;
  snr->snr_v = 0.0;

#ifndef WIN32
  rewind ( p_ref );
#endif

  if ( RefPicExist )
  {
#ifdef WIN32

    if ( !input->ref_pic_order ) //ref order
    {
#if EXTEND_BD
      status = _lseeki64 ( p_ref, nOutputSampleSize * framesize_in_bytes * (background_number-1) , SEEK_SET );
#else
      status = _lseeki64 ( p_ref, framesize_in_bytes * (background_number-1) , SEEK_SET );
#endif
    }
    else
    {
#if EXTEND_BD
      status = _lseeki64 ( p_ref, nOutputSampleSize * framesize_in_bytes * (background_number-1), SEEK_SET );
#else
      status = _lseeki64 ( p_ref, framesize_in_bytes * (background_number-1), SEEK_SET );
#endif
    }

#else

    if ( !input->ref_pic_order ) //ref order
    {
#if EXTEND_BD
      status = fseeko ( p_ref, (off_t)(nOutputSampleSize * framesize_in_bytes * (background_number-1)), 0 );
#else
      status = fseek ( p_ref, framesize_in_bytes * (background_number-1), 0 );
#endif
    }
    else
    {
#if EXTEND_BD
      status = fseeko ( p_ref, (off_t)(nOutputSampleSize * framesize_in_bytes * (background_number-1)), 0 );
#else
      status = fseek ( p_ref, framesize_in_bytes * (background_number-1), 0 );
#endif
    }

#endif

#ifdef WIN32

    if ( status == -1 )
#else
    if ( status != 0 )
#endif
    {
      snprintf ( errortext, ET_SIZE, "Error in seeking img->tr: %d", img->tr );
      RefPicExist = 0;
    }
  }

#ifdef WIN32

  if ( !input->yuv_structure )
  {
#if EXTEND_BD
    _read ( p_ref, buf, nOutputSampleSize * bytes_y );
#else
    _read ( p_ref, buf, bytes_y );
#endif
  }
  else
  {
#if EXTEND_BD
    _read ( p_ref, buf, nOutputSampleSize * (bytes_y + 2 * bytes_uv) );
#else
    _read ( p_ref, buf, bytes_y + 2 * bytes_uv );
#endif
  }

  if ( !input->yuv_structure ) //YUV
  {
    for ( j = 0; j < img_height; j++ )
    {
#if EXTEND_BD
      if (input->output_bit_depth == 8)
      {
        for ( i = 0; i < img_width; i++)
        {
          imgYRef[j][i] = buf[j * img_width + i];
          imgYRef[j][i] &= 0xff; // reset high 8 bits
        }
      }
      else if (input->output_bit_depth == 10)
      {
        for ( i = 0; i < img_width; i++)
        {
          imgYRef[j][i] = ((byte *)buf)[j * img_width + i] & 0x3ff;
        }
      }
      else if (input->output_bit_depth == 12)
      {
        for ( i = 0; i < img_width; i++)
        {
          imgYRef[j][i] = ((byte *)buf)[j * img_width + i] & 0xfff;
        }
      }

#else
      memcpy ( &imgYRef[j][0], buf + j * img_width, img_width );
#endif
    }
  }
  else  //U0Y0 V1Y1
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
#if EXTEND_BD
        if (input->output_bit_depth == 8)
        {
          offset_units = j * img_width + i;
          imgYRef[j][i] = buf[2 * offset_units + 1];
          imgYRef[j][i] &= 0xff;
          if ( offset_units % 2 == 0 ) //U component
          {
            imgUVRef[0][j][i / 2] = buf[2 * offset_units];
          }
          else                  //V component
          {
            imgUVRef[1][j][i / 2] = buf[2 * offset_units];
          }
        }
        else if (input->output_bit_depth == 10)
        {
          offset_units = j * img_width + i;
          imgYRef[j][i] = ((byte *)buf)[2 * offset_units + 1];
          imgYRef[j][i] = imgYRef[j][i] & 0x3ff;
          if ( offset_units % 2 == 0 ) //U component
          {
            imgUVRef[0][j][i / 2] = ((byte *)buf)[2 * offset_units];
            imgUVRef[0][j][i / 2] &= 0x3ff;
          }
          else                  //V component
          {
            imgUVRef[1][j][i / 2] = ((byte *)buf)[2 * offset_units];
            imgUVRef[1][j][i / 2] &= 0x3ff;
          }
        }
        else if (input->output_bit_depth == 12)
        {
          offset_units = j * img_width + i;
          imgYRef[j][i] = ((byte *)buf)[2 * offset_units + 1];
          imgYRef[j][i] = imgYRef[j][i] & 0xfff;
          if ( offset_units % 2 == 0 ) //U component
          {
            imgUVRef[0][j][i / 2] = ((byte *)buf)[2 * offset_units];
            imgUVRef[0][j][i / 2] &= 0xfff;
          }
          else                  //V component
          {
            imgUVRef[1][j][i / 2] = ((byte *)buf)[2 * offset_units];
            imgUVRef[1][j][i / 2] &= 0xfff;
          }
        }

#else
        offset_units = j * img_width + i;
        imgYRef[j][i] = buf[2 * offset_units + 1];

        if ( offset_units % 2 == 0 ) //U component
        {
          imgUVRef[0][j][i / 2] = buf[2 * offset_units];
        }
        else                  //V component
        {
          imgUVRef[1][j][i / 2] = buf[2 * offset_units];
        }
#endif
      }
    }
  }

#else
#if EXTEND_BD
  if ( !input->yuv_structure )
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        if (input->output_bit_depth == 8)
        {
          chTemp[0] = fgetc( p_ref );
          imgYRef[j][i] = chTemp[0];
        }
        else if (input->output_bit_depth == 10)
        {
          chTemp[0] = fgetc( p_ref );
          chTemp[1] = fgetc( p_ref );
          imgYRef[j][i] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
        }
        else if (input->output_bit_depth == 12)
        {
          chTemp[0] = fgetc( p_ref );
          chTemp[1] = fgetc( p_ref );
          imgYRef[j][i] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
        }
      }
    }
  }
  else
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        if (input->output_bit_depth == 8)
        {
          offset_units = j * img_width + i;
          if ( offset_units % 2 == 0 ) //U component
          {
            imgUVRef[0][j][i / 2] = fgetc ( p_ref );
          }
          else          //V component
          {
            imgUVRef[1][j][i / 2] = fgetc ( p_ref );
          }

          imgYRef[j][i] = fgetc ( p_ref );
        }
        else if (input->output_bit_depth == 10)
        {
          offset_units = j * img_width + i;
          if ( offset_units % 2 == 0 ) //U component
          {
            chTemp[0] = fgetc( p_ref );
            chTemp[1] = fgetc( p_ref );
            imgUVRef[0][j][i / 2] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
          }
          else          //V component
          {
            chTemp[0] = fgetc( p_ref );
            chTemp[1] = fgetc( p_ref );
            imgUVRef[1][j][i / 2] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
          }
          chTemp[0] = fgetc( p_ref );
          chTemp[1] = fgetc( p_ref );
          imgYRef[j][i] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
        }
        else if (input->output_bit_depth == 12)
        {
          offset_units = j * img_width + i;
          if ( offset_units % 2 == 0 ) //U component
          {
            chTemp[0] = fgetc( p_ref );
            chTemp[1] = fgetc( p_ref );
            imgUVRef[0][j][i / 2] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
          }
          else          //V component
          {
            chTemp[0] = fgetc( p_ref );
            chTemp[1] = fgetc( p_ref );
            imgUVRef[1][j][i / 2] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
          }
          chTemp[0] = fgetc( p_ref );
          chTemp[1] = fgetc( p_ref );
          imgYRef[j][i] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
        }
      }
    }
  }
#else
  if ( !input->yuv_structure )
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        imgYRef[j][i] = fgetc ( p_ref );
      }
    }
  }
  else
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        offset_units = j * img_width + i;

        if ( offset_units % 2 == 0 ) //U component
        {
          imgUVRef[0][j][i / 2] = fgetc ( p_ref );
        }
        else          //V component
        {
          imgUVRef[1][j][i / 2] = fgetc ( p_ref );
        }

        imgYRef[j][i] = fgetc ( p_ref );
      }
    }
  }
#endif
#endif

  for ( uv = 0; uv < 2; uv++ )
  {
    if ( !input->yuv_structure )
    {
#ifdef WIN32
#if EXTEND_BD
      _read ( p_ref, buf, nOutputSampleSize * img_height_cr * img_width_cr );
#else
      _read ( p_ref, buf, img_height_cr * img_width_cr );
#endif

      for ( j = 0; j < img_height_cr; j++ )
      {
#if EXTEND_BD
        for ( i = 0; i < img_width_cr; i++)
        {
          if (input->output_bit_depth == 8)
          {            
            imgUVRef[uv][j][i] = buf[j * img_width_cr + i];
            imgUVRef[uv][j][i] &= 0xff;
          }
          else if (input->output_bit_depth == 10)
          {
            imgUVRef[uv][j][i] = ((byte *)buf)[j * img_width_cr + i] & 0x3ff;
          }
          else if (input->output_bit_depth == 12)
          {
            imgUVRef[uv][j][i] = ((byte *)buf)[j * img_width_cr + i] & 0xfff;
          }
        }
#else
        memcpy ( &imgUVRef[uv][j][0], buf + j * img_width_cr, img_width_cr );
#endif
      }

#else

      for ( j = 0; j < img_height_cr; j++ )
      {
        for ( i = 0; i < img_width_cr; i++ )
        {
#if EXTEND_BD
          if (input->output_bit_depth == 8)
          {
            imgUVRef[uv][j][i] = fgetc ( p_ref );
          }
          else if (input->output_bit_depth == 10)
          {
            chTemp[0] = fgetc ( p_ref );
            chTemp[1] = fgetc ( p_ref );
            imgUVRef[uv][j][i] = ((byte *)(&(chTemp[0])))[0] & 0x3ff;
          }
          else if (input->output_bit_depth == 12)
          {
            chTemp[0] = fgetc ( p_ref );
            chTemp[1] = fgetc ( p_ref );
            imgUVRef[uv][j][i] = ((byte *)(&(chTemp[0])))[0] & 0xfff;
          }
#else
          imgUVRef[uv][j][i] = fgetc ( p_ref );
#endif
        }
      }

#endif
    }
  }

  img->quad[0] = 0;
  diff_y = 0;

  for ( j = 0; j < img_height; ++j )
  {
    for ( i = 0; i < img_width; ++i )
    {
#if EXTEND_BD
      if (nBitDepthDiff == 0)
      {
        diff_y += img->quad[abs ( imgY[j][i] - imgYRef[j][i] ) ];
      }
      else if (nBitDepthDiff > 0)
      {
        diff_y += img->quad[abs ( Clip1((imgY[j][i] + (1 << (nBitDepthDiff - 1))) >> nBitDepthDiff)  - imgYRef[j][i] ) ];
      }

#else
      diff_y += img->quad[abs ( imgY[j][i] - imgYRef[j][i] ) ];
#endif
    }
  }

  // Chroma
  diff_u = 0;
  diff_v = 0;

  for ( j = 0; j < img_height_cr; ++j )
  {
    for ( i = 0; i < img_width_cr; ++i )
    {
#if EXTEND_BD
      if (nBitDepthDiff == 0)
      {
        diff_u += img->quad[abs ( imgUVRef[0][j][i] - imgUV[0][j][i] ) ];
        diff_v += img->quad[abs ( imgUVRef[1][j][i] - imgUV[1][j][i] ) ];
      }
      else if (nBitDepthDiff > 0)
      {
        diff_u += img->quad[abs ( imgUVRef[0][j][i] - Clip1((imgUV[0][j][i] + (1 << (nBitDepthDiff - 1))) >> nBitDepthDiff) ) ];
        diff_v += img->quad[abs ( imgUVRef[1][j][i] - Clip1((imgUV[1][j][i] + (1 << (nBitDepthDiff - 1))) >> nBitDepthDiff) ) ];
      }
#else
      diff_u += img->quad[abs ( imgUVRef[0][j][i] - imgUV[0][j][i] ) ];
      diff_v += img->quad[abs ( imgUVRef[1][j][i] - imgUV[1][j][i] ) ];
#endif
    }
  }

  // Collecting SNR statistics
  if ( diff_y != 0 )
  {
#if EXTEND_BD
    snr->snr_y = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) );  // luma snr for current frame
#else
    snr->snr_y = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) );  // luma snr for current frame
#endif
  }

  if ( diff_u != 0 )
  {
#if EXTEND_BD
    snr->snr_u = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) );  //  chroma snr for current frame,422
#else
    snr->snr_u = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) );  //  chroma snr for current frame,422
#endif
  }

  if ( diff_v != 0 )
  {
#if EXTEND_BD
    snr->snr_v = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) );  //  chroma snr for current frame,422
#else
    snr->snr_v = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) );  //  chroma snr for current frame,422
#endif
  }

  if ( img->number == /*0*/1 ) // first
  {
#if EXTEND_BD
    snr->snr_y1 = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) ); // keep luma snr for first frame
    snr->snr_u1 = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) ); // keep chroma snr for first frame,422
    snr->snr_v1 = ( float ) ( 10 * log10 ( ((1 << input->output_bit_depth) - 1) * ((1 << input->output_bit_depth) - 1) * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) ); // keep chroma snr for first frame,422
#else
    snr->snr_y1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) ); // keep luma snr for first frame
    snr->snr_u1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) ); // keep chroma snr for first frame,422
    snr->snr_v1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) ); // keep chroma snr for first frame,422
#endif
    snr->snr_ya = snr->snr_y1;
    snr->snr_ua = snr->snr_u1;
    snr->snr_va = snr->snr_v1;

    if ( diff_y == 0 )
    {
      snr->snr_ya =/*50*/0;
    }

    if ( diff_u == 0 )
    {
      snr->snr_ua =/*50*/0;
    }

    if ( diff_v == 0 )
    {
      snr->snr_va =/*50*/0;
    }
  }
  else
  {
    snr->snr_ya = ( float ) ( snr->snr_ya * ( img->number + Bframe_ctr - 1 ) + snr->snr_y ) / ( img->number + Bframe_ctr ); // average snr chroma for all frames 20080721
    snr->snr_ua = ( float ) ( snr->snr_ua * ( img->number + Bframe_ctr - 1 ) + snr->snr_u ) / ( img->number + Bframe_ctr ); // average snr luma for all frames 20080721
    snr->snr_va = ( float ) ( snr->snr_va * ( img->number + Bframe_ctr - 1 ) + snr->snr_v ) / ( img->number + Bframe_ctr ); // average snr luma for all frames 20080721
  }

  free ( buf );
}
#else
#ifdef AVS2_S2_BGLONGTERM
/*
*************************************************************************
* Function:Find PSNR for background frame.Compare decoded frame with
the original sequence. Read input->jumpd frames to reflect frame skipping.
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
#ifdef WIN32
void find_snr_background (SNRParameters *snr, int p_ref )
#else
void find_snr_background (SNRParameters *snr, FILE *p_ref )          //!< filestream to reference YUV file
#endif
{
  int i, j;
  int diff_y, diff_u, diff_v;
  int uv;
  int uvformat = input->chroma_format == 1 ? 4 : 2;
#ifdef WIN32
  __int64 status;
#else
  int  status;
#endif

  int img_width = ( img->width - img->auto_crop_right );
  int img_height = ( img->height - img->auto_crop_bottom );
  int img_width_cr = ( img_width / 2 );
  int img_height_cr = ( img_height / ( input->chroma_format == 1 ? 2 : 1 ) );
#ifdef WIN32
  const unsigned int  bytes_y = img_width * img_height;
  const unsigned int  bytes_uv = img_width_cr * img_height_cr;
  const __int64 framesize_in_bytes = ( __int64 ) ( bytes_y + 2 * bytes_uv );
#else
  const unsigned int  bytes_y = img_width * img_height;
  const unsigned int  bytes_uv = img_width_cr * img_height_cr;
  const int framesize_in_bytes = bytes_y + 2 * bytes_uv;
#endif
  unsigned char *buf;
  int   offset_units;

  if ( !input->yuv_structure )
  {
    buf = malloc ( bytes_y );
  }
  else
  {
    buf = malloc ( bytes_y + 2 * bytes_uv );
  }

  if ( NULL == buf )
  {
    no_mem_exit ( "find_snr: buf" );
  }

  snr->snr_y = 0.0;
  snr->snr_u = 0.0;
  snr->snr_v = 0.0;

#ifndef WIN32
  rewind ( p_ref );
#endif

  if ( RefPicExist )
  {
#ifdef WIN32

    if ( !input->ref_pic_order ) //ref order
    {
     status = _lseeki64 ( p_ref, framesize_in_bytes * (background_number-1) , SEEK_SET );
    }
    else
    {
      status = _lseeki64 ( p_ref, framesize_in_bytes * (background_number-1), SEEK_SET );
    }

#else

    if ( !input->ref_pic_order ) //ref order
    {
      status = fseek ( p_ref, framesize_in_bytes * ( img->type == B_IMG ? img->tr : FrameNum ), 0 );
    }
    else
    {
      status = fseek ( p_ref, framesize_in_bytes * dec_ref_num, 0 );
    }

#endif

#ifdef WIN32

    if ( status == -1 )
#else
    if ( status != 0 )
#endif
    {
      snprintf ( errortext, ET_SIZE, "Error in seeking img->tr: %d", img->tr );
      RefPicExist = 0;
    }
  }

#ifdef WIN32

  if ( !input->yuv_structure )
  {
    _read ( p_ref, buf, bytes_y );
  }
  else
  {
    _read ( p_ref, buf, bytes_y + 2 * bytes_uv );
  }

  if ( !input->yuv_structure ) //YUV
  {
    for ( j = 0; j < img_height; j++ )
    {
      memcpy ( &imgYRef[j][0], buf + j * img_width, img_width );
    }
  }
  else  //U0Y0 V1Y1
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        offset_units = j * img_width + i;
        imgYRef[j][i] = buf[2 * offset_units + 1];

        if ( offset_units % 2 == 0 ) //U component
        {
          imgUVRef[0][j][i / 2] = buf[2 * offset_units];
        }
        else                  //V component
        {
          imgUVRef[1][j][i / 2] = buf[2 * offset_units];
        }
      }
    }
  }

#else

  if ( !input->yuv_structure )
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        imgYRef[j][i] = fgetc ( p_ref );
      }
    }
  }
  else
  {
    for ( j = 0; j < img_height; j++ )
    {
      for ( i = 0; i < img_width; i++ )
      {
        offset_units = j * img_width + i;

        if ( offset_units % 2 == 0 ) //U component
        {
          imgUVRef[0][j][i / 2] = fgetc ( p_ref );
        }
        else          //V component
        {
          imgUVRef[1][j][i / 2] = fgetc ( p_ref );
        }

        imgYRef[j][i] = fgetc ( p_ref );
      }
    }
  }

#endif

  for ( uv = 0; uv < 2; uv++ )
  {
    if ( !input->yuv_structure )
    {
#ifdef WIN32
      _read ( p_ref, buf, img_height_cr * img_width_cr );

      for ( j = 0; j < img_height_cr; j++ )
      {
        memcpy ( &imgUVRef[uv][j][0], buf + j * img_width_cr, img_width_cr );
      }

#else

      for ( j = 0; j < img_height_cr; j++ )
      {
        for ( i = 0; i < img_width_cr; i++ )
        {
          imgUVRef[uv][j][i] = fgetc ( p_ref );
        }
      }

#endif
    }
  }

  img->quad[0] = 0;
  diff_y = 0;

  for ( j = 0; j < img_height; ++j )
  {
    for ( i = 0; i < img_width; ++i )
    {
		diff_y += img->quad[abs ( imgY[j][i] - imgYRef[j][i] ) ];
	}
  }

  // Chroma
  diff_u = 0;
  diff_v = 0;

  for ( j = 0; j < img_height_cr; ++j )
  {
	  for ( i = 0; i < img_width_cr; ++i )
	  {
		  diff_u += img->quad[abs ( imgUVRef[0][j][i] - imgUV[0][j][i] ) ];
		  diff_v += img->quad[abs ( imgUVRef[1][j][i] - imgUV[1][j][i] ) ];
	  }
  }

  // Collecting SNR statistics
  if ( diff_y != 0 )
  {
	  snr->snr_y = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) );  // luma snr for current frame
  }

  if ( diff_u != 0 )
  {
	  snr->snr_u = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) );  //  chroma snr for current frame,422
  }

  if ( diff_v != 0 )
  {
	  snr->snr_v = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) );  //  chroma snr for current frame,422
  }

  if ( img->number == /*0*/1 ) // first
  {
	  snr->snr_y1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) diff_y ) ); // keep luma snr for first frame
	  snr->snr_u1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_u ) ) ); // keep chroma snr for first frame,422
	  snr->snr_v1 = ( float ) ( 10 * log10 ( 65025 * ( float ) ( img_width/*img->width*/ ) * ( img_height/*img->height*/ ) / ( float ) ( /*4*/uvformat * diff_v ) ) ); // keep chroma snr for first frame,422
	  snr->snr_ya = snr->snr_y1;
	  snr->snr_ua = snr->snr_u1;
	  snr->snr_va = snr->snr_v1;

	  if ( diff_y == 0 )
	  {
		  snr->snr_ya =/*50*/0;
	  }

	  if ( diff_u == 0 )
	  {
		  snr->snr_ua =/*50*/0;
	  }

	  if ( diff_v == 0 )
	  {
		  snr->snr_va =/*50*/0;
	  }
  }
  else
  {
	  snr->snr_ya = ( float ) ( snr->snr_ya * ( img->number + Bframe_ctr - 1 ) + snr->snr_y ) / ( img->number + Bframe_ctr ); // average snr chroma for all frames 20080721
	  snr->snr_ua = ( float ) ( snr->snr_ua * ( img->number + Bframe_ctr - 1 ) + snr->snr_u ) / ( img->number + Bframe_ctr ); // average snr luma for all frames 20080721
	  snr->snr_va = ( float ) ( snr->snr_va * ( img->number + Bframe_ctr - 1 ) + snr->snr_v ) / ( img->number + Bframe_ctr ); // average snr luma for all frames 20080721
  }

  free ( buf );
}
#endif //AVS2_S2_BGLONGTERM
#endif //AVS2_SCENE_CD

#if M3480_TEMPORAL_SCALABLE
void cleanRefMVBufRef( int pos )
{
	int i, k, x, y;
	//re-init mvbuf
	for (k=0; k<2; k++)
	{
		for (y=0; y<img->height/MIN_BLOCK_SIZE; y++)
		{
			for (x=0; x<img->width/MIN_BLOCK_SIZE; x++)
			{
				mvbuf[pos][y][x][k] = 0;
			}
		}
	}
	//re-init refbuf
	for ( y = 0; y < img->height / MIN_BLOCK_SIZE; y++ )
	{
		for ( x = 0; x < img->width / MIN_BLOCK_SIZE ; x++ )
		{
			refbuf[pos][y][x] = -1;
		}
	}
}
#endif

void prepare_RefInfo()
{
	int i, j, tmp_coi, tmp_poc ,tmp_refered, tmp_temporal, tmp_is_output;
#if EXTEND_BD
	byte ***tmp_yuv;
#else
	unsigned char ***tmp_yuv;
#endif
	int **tmp_ref;
	int ***tmp_mv;
	int flag=0;
	int tmp_ref_poc[4];

	double *tmp_saorate;

	//////////////////////////////////////////////////////////////////////////
	//update IDR frame
	if (img->tr>next_IDRtr&&curr_IDRtr!=next_IDRtr)
	{
		curr_IDRtr = next_IDRtr;
		curr_IDRcoi = next_IDRcoi;
	}
	//////////////////////////////////////////////////////////////////////////
	// re-order the ref buffer according to RPS
	img->num_of_references = curr_RPS.num_of_ref;

	for ( i=0; i<curr_RPS.num_of_ref; i++ )
	{
		int accumulate = 0;
		tmp_yuv = ref[i];
		tmp_coi = img->imgcoi_ref[i];
#if M3480_TEMPORAL_SCALABLE
		tmp_temporal = img->temporal_id[i];
#endif
#if M3481_REMOVE_BUGFIX
		tmp_is_output = img->is_output[i];
#endif
		tmp_poc = img->imgtr_fwRefDistance[i];
		tmp_refered = img->refered_by_others[i];
		tmp_ref = refbuf[i];
		tmp_mv = mvbuf[i];

		tmp_saorate = saorate[i];

		memcpy(tmp_ref_poc,ref_poc[i],4*sizeof(int));
		for ( j=i; j<REF_MAXBUFFER; j++)///////////////to be modified  IDRÖ¡µÄ´¦Àí
		{
			int k ,tmp_tr;
			for (k=0;k<REF_MAXBUFFER;k++)//²éÕÒ²Î¿¼Ö¡µÄcoi
			{
#if REF_MINUS
				if (((int)img->coding_order - (int)curr_RPS.ref_pic[i]) == img->imgcoi_ref[k] && img->imgcoi_ref[k]>=-256 )
#else
				if (((int)img->coding_order - (int)curr_RPS.ref_pic[i]) == img->imgcoi_ref[k] && img->imgcoi_ref[k]>=0 )
#endif
				{
					break;
				}
			}
			if (k==REF_MAXBUFFER)
			{
				tmp_tr = -1;
			}
			else
			{
				tmp_tr = img->imgtr_fwRefDistance[k];//ÕÒµ½²Î¿¼Ö¡µÄtr
			}
			if ( tmp_tr < curr_IDRtr)//Èô²Î¿¼Ö¡µÄtrÐ¡ÓÚµ±Ç°µÄIDRÖ¡µÄtr£¬Ôò½«refÉèÎªµ±Ç°µÄIDRÖ¡   ÈôÐÂÉèÖÃµÄ²Î¿¼Ö¡ºÍÆäËûµÄ²Î¿¼Ö¡ÖØ¸´£¬Ôònum_ref--
			{
				curr_RPS.ref_pic[i] = img->coding_order - curr_IDRcoi;

				for ( k=0;k<i;k++)
				{
					if (curr_RPS.ref_pic[k]==curr_RPS.ref_pic[i])
					{
						accumulate++;
						break;
					}
				}
			}
			if ( img->imgcoi_ref[j] == img->coding_order - curr_RPS .ref_pic[i])
			{
				break;
			}
		}
		if (j==REF_MAXBUFFER || accumulate)
		{
			img->num_of_references--;
		}
		if ( j != REF_MAXBUFFER )
		{
			ref[i] = ref[j];
			refbuf[i] = refbuf[j];
			mvbuf[i] = mvbuf[j];
			img->imgcoi_ref[i] = img->imgcoi_ref[j];
#if M3480_TEMPORAL_SCALABLE
			img->temporal_id[i] = img->temporal_id[j];
#endif
#if M3481_REMOVE_BUGFIX
			img->is_output[i] = img->is_output[j];
#endif
			img->imgtr_fwRefDistance[i] = img->imgtr_fwRefDistance[j];
			img->refered_by_others[i] = img->refered_by_others[j];

			saorate[i] = saorate[j];
			saorate[j] = tmp_saorate;

			memcpy(ref_poc[i],ref_poc[j],4*sizeof(int));
			ref[j] = tmp_yuv;
			refbuf[j] = tmp_ref;
			mvbuf[j] = tmp_mv;
			img->imgcoi_ref[j] = tmp_coi;
#if M3480_TEMPORAL_SCALABLE
			img->temporal_id[j] = tmp_temporal;
#endif
#if M3481_REMOVE_BUGFIX
			img->is_output[j] = tmp_is_output;
#endif
			img->imgtr_fwRefDistance[j] = tmp_poc;
			img->refered_by_others[j] = tmp_refered;
			memcpy(ref_poc[j],tmp_ref_poc,4*sizeof(int));
		}
	}


	if (img->type==B_IMG&&(img->imgtr_fwRefDistance[0]<=img->tr||img->imgtr_fwRefDistance[1]>=img->tr))
	{
		int max_for=1,k;
		int min_bck=0;
		int tmp_max_for = 0;
		int tmp_min_bck = 1<<30;
		for(i=1;i<REF_MAXBUFFER;i++)
		{
			int tmp_ref = img->imgtr_fwRefDistance[i];
			if (tmp_ref<img->tr && tmp_ref>tmp_max_for && tmp_ref>=curr_IDRtr)
			{
				max_for = i;//find forward ref
				tmp_max_for = tmp_ref;
			}
			if (tmp_ref>img->tr && tmp_ref<tmp_min_bck)
			{
				min_bck = i;//find backward ref
				tmp_min_bck = tmp_ref;
			}
		}
		for (k=0;k<2;k++)
		{
			i = (k==0? max_for:min_bck);
			j = (k==0? 1:0);
			tmp_yuv = ref[i];
			tmp_coi = img->imgcoi_ref[i];
#if M3480_TEMPORAL_SCALABLE
			tmp_temporal = img->temporal_id[i];
#endif
#if M3481_REMOVE_BUGFIX
			tmp_is_output = img->is_output[i];
#endif
			tmp_poc = img->imgtr_fwRefDistance[i];
			tmp_refered = img->refered_by_others[i];
			tmp_ref = refbuf[i];
			tmp_mv = mvbuf[i];
			tmp_saorate = saorate[i];
			memcpy(tmp_ref_poc,ref_poc[i],4*sizeof(int));
			ref[i] = ref[j];
			integerRefY[i] =integerRefY[j];
			refbuf[i] = refbuf[j];
			mvbuf[i] = mvbuf[j];
			img->imgcoi_ref[i] = img->imgcoi_ref[j];
#if M3480_TEMPORAL_SCALABLE
			img->temporal_id[i] = img->temporal_id[j];
#endif
#if M3481_REMOVE_BUGFIX
			img->is_output[i] = img->is_output[j];
#endif
			img->imgtr_fwRefDistance[i] = img->imgtr_fwRefDistance[j];
			img->refered_by_others[i] = img->refered_by_others[j];
			saorate[i] = saorate[j];
			saorate[j] = tmp_saorate;
			memcpy(ref_poc[i],ref_poc[j],4*sizeof(int));
			ref[j] = tmp_yuv;
			refbuf[j] = tmp_ref;
			mvbuf[j] = tmp_mv;
			img->imgcoi_ref[j] = tmp_coi;
#if M3480_TEMPORAL_SCALABLE
			img->temporal_id[j] = tmp_temporal;
#endif
#if M3481_REMOVE_BUGFIX
			img->is_output[j] = tmp_is_output;
#endif
			img->imgtr_fwRefDistance[j] = tmp_poc;
			img->refered_by_others[j] = tmp_refered;
			memcpy(ref_poc[j],tmp_ref_poc,4*sizeof(int));
		}
	}


	//////////////////////////////////////////////////////////////////////////
#if DHP
	if ((img->type==F_IMG)||(img->type==P_IMG))
#else
	if (img->type==P_IMG)
#endif
	{
#if !XL_ADDED			// Xiaolong Delete 
		for (i=img->num_of_references;i<curr_RPS.num_of_ref;i++)
		{
			int max_for=img->num_of_references;
			int tmp_max_for = curr_IDRtr;
			int flag = 0;
			for (j=img->num_of_references;j<REF_MAXBUFFER;j++)
			{
				int tmp_ref = img->imgtr_fwRefDistance[j];
#if M3480_TEMPORAL_SCALABLE
				if ( tmp_ref<img->tr && tmp_ref>curr_IDRtr && ( temporal_id_exist_flag != 1 || cur_layer >= img->temporal_id[ j ] ) && abs(img->imgtr_fwRefDistance[j] - img->tr)<128 )
#else
				if( tmp_ref<img->tr && tmp_ref>curr_IDRtr )
#endif
				{
					flag = 1;
					max_for = j;//find forward ref
					tmp_max_for = tmp_ref;
				}
			}
			if (flag)
			{
				if (max_for!=img->num_of_references)
				{
					j=max_for;
					tmp_yuv = ref[i];
#if M3480_TEMPORAL_SCALABLE
					tmp_temporal = img->temporal_id[i];
#endif
#if M3481_REMOVE_BUGFIX
					tmp_is_output = img->is_output[i];
#endif
					tmp_coi = img->imgcoi_ref[i];
					tmp_poc = img->imgtr_fwRefDistance[i];
					tmp_refered = img->refered_by_others[i];
					tmp_ref = refbuf[i];
					tmp_mv = mvbuf[i];
					tmp_saorate = saorate[i];
					memcpy(tmp_ref_poc,ref_poc[i],4*sizeof(int));
					ref[i] = ref[j];
					refbuf[i] = refbuf[j];
					mvbuf[i] = mvbuf[j];
					img->imgcoi_ref[i] = img->imgcoi_ref[j];
#if M3480_TEMPORAL_SCALABLE
					img->temporal_id[i] = img->temporal_id[j];
#endif
#if M3481_REMOVE_BUGFIX
					img->is_output[i] = img->is_output[j];
#endif
					img->imgtr_fwRefDistance[i] = img->imgtr_fwRefDistance[j];
					img->refered_by_others[i] = img->refered_by_others[j];
					saorate[i] = saorate[j];
					saorate[j] = tmp_saorate;
					memcpy(ref_poc[i],ref_poc[j],4*sizeof(int));
					ref[j] = tmp_yuv;
					refbuf[j] = tmp_ref;
					mvbuf[j] = tmp_mv;
					img->imgcoi_ref[j] = tmp_coi;
#if M3480_TEMPORAL_SCALABLE
					img->temporal_id[j] = tmp_temporal;
#endif
#if M3481_REMOVE_BUGFIX
					img->is_output[j] = tmp_is_output;
#endif
					img->imgtr_fwRefDistance[j] = tmp_poc;
					img->refered_by_others[j] = tmp_refered;
					memcpy(ref_poc[j],tmp_ref_poc,4*sizeof(int));
				}
				flag = 0;
				img->num_of_references++;
			}
			else
			{
				break;
			}
		}
#endif
    /*  //bug fixed for motion compression
		for (j=0; j<img->height/MIN_BLOCK_SIZE; j++)
		{
			for (i=0; i<img->width/MIN_BLOCK_SIZE; i++)
			{
				refbuf[0][j][i] = refFrArr[j][i];
			}
		}
    */
	}

	//////////////////////////////////////////////////////////////////////////
	// delete the frame that will never be used
	for ( i=0; i< curr_RPS.num_to_remove; i++)
	{
		for ( j=0; j<REF_MAXBUFFER; j++)
		{
#if REF_MINUS
			if ( img->imgcoi_ref[j]>=-256 && img->imgcoi_ref[j] == img->coding_order - curr_RPS.remove_pic[i])
#else
			if ( img->imgcoi_ref[j]>=0 && img->imgcoi_ref[j] == img->coding_order - curr_RPS.remove_pic[i])
#endif
			{
				break;
			}
		}
		if (j<REF_MAXBUFFER && j>=img->num_of_references)
		{
#if REF_MINUS
			img->imgcoi_ref[j] = -257;
#if M3480_TEMPORAL_SCALABLE
			img->temporal_id[j] = -1;
#endif
#if M3481_REMOVE_BUGFIX
			if( img->is_output[j] == -1 )
#endif
				img->imgtr_fwRefDistance[j] = -256;
#else
			img->imgcoi_ref[j] = -1;
#if M3480_TEMPORAL_SCALABLE
			img->temporal_id[j] = -1;
#endif
#if M3481_REMOVE_BUGFIX
			if( img->is_output[j] == -1 )
#endif
			img->imgtr_fwRefDistance[j] = 0;
#endif
		}
	}

	//////////////////////////////////////////////////////////////////////////
	//   add current frame to ref buffer
	for ( i=0; i<REF_MAXBUFFER; i++ )
	{
#if M3481_REMOVE_BUGFIX
#if !M3481_REMOVE_BUGFIX2
		if ( ( img->imgcoi_ref[i] < 0 || abs(img->imgtr_fwRefDistance[i] - img->tr)>=128 ) && img->is_output[i] == -1 )
#else 
		if ( ( img->imgcoi_ref[i] < -256 || abs(img->imgtr_fwRefDistance[i] - img->tr)>=128 ) && img->is_output[i] == -1 )
#endif 
#else
#if REF_MINUS
		if ( img->imgcoi_ref[i] < -256 || abs(img->imgtr_fwRefDistance[i] - img->tr)>=128 )
#else
		if ( img->imgcoi_ref[i] < 0 || abs(img->imgtr_fwRefDistance[i] - img->tr)>=128 )
#endif
#endif
		{
			break;
		}
	}
	if ( i == REF_MAXBUFFER )
	{
		i--;
	}

#if MULTIVIEW_CODING
	currPosInDPB = i;
#endif

	currentFrame = ref[i];
	img->imgtr_fwRefDistance[i] = img->tr;
	img->imgcoi_ref[i] = img->coding_order;
#if M3480_TEMPORAL_SCALABLE
	img->temporal_id[i] = cur_layer;
#endif
#if M3481_REMOVE_BUGFIX
	img->is_output[i] = 1;
#endif
	img->refered_by_others[i] = curr_RPS.referd_by_others;

	if (img->type != B_IMG)
	{
		for (j=0;j<img->num_of_references;j++)
		{
			ref_poc[i][j] = img->imgtr_fwRefDistance[j];
		}
#if M3480_TEMPORAL_SCALABLE
#if MULTIVIEW_CODING
		for (j=img->num_of_references; j<4; j++)
		{
			ref_poc[i][j] = -256;
		}
#else
		for (j=img->num_of_references; j<4; j++)
		{
			ref_poc[i][j] = 0;
		}
#endif
#endif
	}
	else
	{
		ref_poc[i][0] = img->imgtr_fwRefDistance[1];
		ref_poc[i][1] = img->imgtr_fwRefDistance[0];
#if M3480_TEMPORAL_SCALABLE
#if MULTIVIEW_CODING
		ref_poc[i][2] = -256;
		ref_poc[i][3] = -256;
#else
		ref_poc[i][2] = 0;
		ref_poc[i][3] = 0;
#endif
#endif
	}
#if M3480_TEMPORAL_SCALABLE
	if( img->type == INTRA_IMG )
	{
		int l;
		for( l = 0; l < 4; l ++ )
			ref_poc[i][l] = img->tr;
	}
	cleanRefMVBufRef( i );
#endif

	for (j=0; j<NUM_SAO_COMPONENTS; j++)
	{
		saorate[i][j] = img->cur_saorate[j];
	}

	//printf("%d %d %d %d %d %d %d %d %d\n",img->num_of_references,img->imgtr_fwRefDistance[0],img->imgtr_fwRefDistance[1],img->imgtr_fwRefDistance[2],img->imgtr_fwRefDistance[3],img->imgtr_fwRefDistance[4],img->imgtr_fwRefDistance[5],img->imgtr_fwRefDistance[6],img->imgtr_fwRefDistance[7]);


#if MULTIVIEW_CODING
	// add the inter-view reference frame

	if(img->view_index > 0 && img->type != I_IMG && img->type != B_IMG)

	{

		if(img -> bDepth == 0)
		{

			//record the position of inter view reference picture in the base view, baseview index number is 0
			int interViewRefPos = 0;
			//the position of inter view reference frame in current frame list
			int interViewRefInCurrRefListPos = 0;

			//store the current reference frame list, which only include the reference frame from current view
			for( i = 0; i < REF_MAXBUFFER; i ++)
			{
				currView_ref[i] = ref[i];
				currView_mvbuf[i] = mvbuf[i];
				currView_refbuf[i] = refbuf[i];

				img->currView_imgtr_fwRefDistance[i] = img->imgtr_fwRefDistance[i];
				img->currView_imgcoi_ref[i] = img->imgcoi_ref[i];
				img->currView_refered_by_others[i] = img->refered_by_others[i];
				memcpy(currView_ref_poc[i], ref_poc[i], 4*sizeof(int));

				for (j = 0; j < 3; j ++)
				{
					currView_saorate[i][j]	    	 = saorate[i][j];
				}

			}


			//   find the inter-view reference frame
			for ( i=0; i<REF_MAXBUFFER; i++ )
			{
				if ( img->multiView_imgtr_fwRefDistance[0][i] == img->tr)
				{
					break;
				}
			}
			if( i < REF_MAXBUFFER)
			{
				interViewRefPos = i;
			}
			else
			{
				return;
			}

#if DHP
			if ((img->type==P_IMG)||(img->type==F_IMG))
#else
			if (img->type==INTER_IMG)
#endif
			{
				//insert the inter view reference frame into the tail of the reference list

				interViewRefInCurrRefListPos = img->num_of_references == 4 ? 3 : img->num_of_references;

			}
			//assign the inter view reference frame pointer to the specified position
			ref[interViewRefInCurrRefListPos]    = multiView_ref[0][interViewRefPos];
			mvbuf[interViewRefInCurrRefListPos]  = multiView_mvbuf[0][interViewRefPos];
			refbuf[interViewRefInCurrRefListPos] = multiView_refbuf[0][interViewRefPos];

			img->imgtr_fwRefDistance[interViewRefInCurrRefListPos] = img->multiView_imgtr_fwRefDistance[0][interViewRefPos];
			img->imgcoi_ref[interViewRefInCurrRefListPos]          = img->multiView_imgcoi_ref[0][interViewRefPos];
			img->refered_by_others[interViewRefInCurrRefListPos]   =img->multiView_refered_by_others[0][interViewRefPos];

			memcpy(ref_poc[interViewRefInCurrRefListPos], multiView_ref_poc[0][interViewRefPos], 4*sizeof(int));

			for (j = 0; j < 3; j ++)
			{
				saorate[interViewRefInCurrRefListPos][j]	    	 = multiView_saorate[0][interViewRefPos][j];
			}


			//
			curr_RPS.ref_pic[interViewRefInCurrRefListPos] = 0;

			// the number of reference frames ++
			if(img->num_of_references < 4)
			{
				img->num_of_references ++;
			}

			curr_RPS.num_of_ref = img->num_of_references;

			ref_poc[currPosInDPB][interViewRefInCurrRefListPos] = img->tr;
			currView_ref_poc[currPosInDPB][interViewRefInCurrRefListPos] = img->tr;
		}


		if(img -> bDepth == 1)
		{
			//record the position of inter view reference picture in the base view, baseview index number is 0
			int interViewRefPos = 0;
			//the position of inter view reference frame in current frame list
			int interViewRefInCurrRefListPos = 0;

			//store the current reference frame list, which only include the reference frame from current view
			for( i = 0; i < REF_MAXBUFFER; i ++)
			{
				currView_ref[i] = ref[i];
				currView_mvbuf[i] = mvbuf[i];
				currView_refbuf[i] = refbuf[i];

				img->currView_imgtr_fwRefDistance[i] = img->imgtr_fwRefDistance[i];
				img->currView_imgcoi_ref[i] = img->imgcoi_ref[i];
				img->currView_refered_by_others[i] = img->refered_by_others[i];
				memcpy(currView_ref_poc[i], ref_poc[i], 4*sizeof(int));

				for (j = 0; j < 3; j ++)
				{
					currView_saorate[i][j]	    	 = saorate[i][j];
				}

			}


			//   find the inter-view reference frame
			for ( i=0; i<REF_MAXBUFFER; i++ )
			{
				if ( img->multiView_depth_imgtr_fwRefDistance[0][i] == img->tr)
				{
					break;
				}
			}
			if( i < REF_MAXBUFFER)
			{
				interViewRefPos = i;
			}
			else
			{
				return;
			}

#if DHP
			if ((img->type==P_IMG)||(img->type==F_IMG))
#else
			if (img->type==INTER_IMG)
#endif
			{
				//insert the inter view reference frame into the tail of the reference list

				interViewRefInCurrRefListPos = img->num_of_references == 4 ? 3 : img->num_of_references;

			}
			//assign the inter view reference frame pointer to the specified position
			ref[interViewRefInCurrRefListPos]    = multiView_depth_ref[0][interViewRefPos];
			mvbuf[interViewRefInCurrRefListPos]  = multiView_depth_mvbuf[0][interViewRefPos];
			refbuf[interViewRefInCurrRefListPos] = multiView_depth_refbuf[0][interViewRefPos];

			img->imgtr_fwRefDistance[interViewRefInCurrRefListPos] = img->multiView_depth_imgtr_fwRefDistance[0][interViewRefPos];
			img->imgcoi_ref[interViewRefInCurrRefListPos]          = img->multiView_depth_imgcoi_ref[0][interViewRefPos];
			img->refered_by_others[interViewRefInCurrRefListPos]   = img->multiView_depth_refered_by_others[0][interViewRefPos];

			memcpy(ref_poc[interViewRefInCurrRefListPos], multiView_depth_ref_poc[0][interViewRefPos], 4*sizeof(int));

			for (j = 0; j < 3; j ++)
			{
				saorate[interViewRefInCurrRefListPos][j]	    	 = multiView_depth_saorate[0][interViewRefPos][j];
			}


			//
			curr_RPS.ref_pic[interViewRefInCurrRefListPos] = 0;

			// the number of reference frames ++
			if(img->num_of_references < 4)
			{
				img->num_of_references ++;
			}

			curr_RPS.num_of_ref = img->num_of_references;
			ref_poc[currPosInDPB][interViewRefInCurrRefListPos] = img->tr;
			currView_ref_poc[currPosInDPB][interViewRefInCurrRefListPos] = img->tr;
		}

	}
#endif

	//////////////////////////////////////////////////////////////////////////
	// update ref pointer

	if ( img->type!=I_IMG )
	{
		for ( j = 0; j < 4; j++ ) //ref_index = 0
		{
			integerRefY[j] = ref[j][0];
		}
		for ( j = 0; j < 4; j++ ) //ref_index = 0
		{
			for ( i = 0; i < 2; i++ ) // chroma uv =0,1; 1,2 for referenceFrame
			{
				integerRefUV[j][i] = ref[j][i + 1];
			}
		}
		//forward/backward reference buffer
		f_ref[0] = ref[1]; //f_ref[ref_index][yuv][height(height/2)][width] ref_index=0 for B frame, ref_index = 0,1 for B field
		b_ref[0] = ref[0]; //b_ref[ref_index][yuv][height(height/2)][width] ref_index=0 for B frame, ref_index = 0,1 for B field
		for ( j = 0; j < 1; j++ ) //ref_index = 0 luma = 0
		{
			integerRefY_fref[j] = f_ref[j][0];
			integerRefY_bref[j] = b_ref[j][0];
		}
		//chroma for backward
		for ( j = 0; j < 1; j++ ) //ref_index = 0
		{
			for ( i = 0; i < 2; i++ ) // chroma uv =0,1; 1,2 for referenceFrame
			{
				integerRefUV_fref[j][i] = f_ref[j][i + 1];
				integerRefUV_bref[j][i] = b_ref[j][i + 1];
			}
		}
		img->imgtr_next_P = img->type == B_IMG? img->imgtr_fwRefDistance[0] : img->tr;
		if (img->type==B_IMG)
		{
			trtmp = img->imgtr_fwRefDistance[0];
			img->imgtr_fwRefDistance[0] = img->imgtr_fwRefDistance[1];
		}
	}
#ifdef AVS2_S2_S
	{
		int k,x,y,ii;
		for(ii = 0; ii < 8; ii++)
		{
			for ( k = 0; k < 2; k++ )
			{
				for ( y = 0; y < img->height / MIN_BLOCK_SIZE; y++ )
				{
					for ( x = 0; x < img->width / MIN_BLOCK_SIZE ; x++ )
					{
						if(img->typeb == BP_IMG)
						{
							mvbuf[ii][y][x][k] = 0;
							refbuf[ii][y][x] = 0;
						}
					}
				}
			}
		}
	}
#endif
}
/*
*************************************************************************
* Function:Interpolation of 1/4 subpixel
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
#if EXTEND_BD
void get_block ( int ref_frame, int x_pos, int y_pos, int step_h, int step_v, int block[MAX_CU_SIZE][MAX_CU_SIZE], byte **ref_pic 
#else
void get_block ( int ref_frame, int x_pos, int y_pos, int step_h, int step_v, int block[MAX_CU_SIZE][MAX_CU_SIZE], unsigned char **ref_pic 
#endif
#ifdef AVS2_S2_SBD
				,int ioff, int joff
#endif				
				)
{
#if EXTEND_BD
	int max_pel_value = (1 << input->sample_bit_depth) - 1;
	int shift1 = input->sample_bit_depth - 8;
	int shift2 = 14 - input->sample_bit_depth;
	int shift3 = 20 - input->sample_bit_depth;
#else
	int max_pel_value = 255;
#endif
  int dx, dy;
  int x, y;
  int i, j;
  int maxold_x, maxold_y;
  int result;
  int tmp_res[140][140];
#ifdef AVS2_S2_SBD
  int tmp_bgr[140][140];
#endif
  int tap, tap_min, tap_max;



  static const int COEF_8tap[3][8] =
  {
      { -1, 4, -10, 57, 19,  -7, 3, -1 },
      { -1, 4, -11, 40, 40, -11, 4, -1 },
      { -1, 3, -7, 19, 57,  -10, 4, -1 }
  };

  const int *COEF[3];
  

 
      COEF[0] = COEF_8tap[0];
      COEF[1] = COEF_8tap[1];
      COEF[2] = COEF_8tap[2];
      tap = 8;
  

  tap_min = (tap>>1) -1;
  tap_max = (tap>>1) +1;

  //    A  a  1  b  B
  //    c  d  e  f
  //    2  h  3  i
  //    j  k  l  m
  //    C           D

  dx = x_pos & 3;
  dy = y_pos & 3;
  x_pos = ( x_pos - dx ) / 4;
  y_pos = ( y_pos - dy ) / 4;
  maxold_x = img->width - 1;
  maxold_y = img->height - 1;

  if ( dx == 0 && dy == 0 )   //fullpel position: A
  {
    for ( j = 0; j < step_v; j++ )
    {
      for ( i = 0; i < step_h; i++ )
      {

#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
	  if(background_reference_enable && img->num_of_references>=2 && ref_frame ==  img->num_of_references-1 && (img->type == P_IMG || img->type == F_IMG) && img->typeb != BP_IMG)
#else
	  if(input->profile_id == 0x50 && background_reference_enable && img->num_of_references>=2 && ref_frame ==  img->num_of_references-1 && img->type == P_IMG && img->typeb != BP_IMG)
#endif
	  {
		  block[j][i] = background_frame[0][max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i ) ) ];
	  }
#ifdef AVS2_S2_S
#if AVS2_SCENE_CD
	  else if(img->typeb == BP_IMG)
#else
	  else if(input->profile_id == 0x50 && img->typeb == BP_IMG)
#endif
	  {
		  block[j][i] = background_frame[0][max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i ) ) ];
	  }
#endif
	  else
	  {
      block[j][i] = ref_pic[max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i ) ) ];
	  }
#else
        block[j][i] = ref_pic[max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i ) ) ];
#endif
      }
    }
  }

  else
  {
    /* other positions */
    if ( dy == 0 )    //horizontal position: a,1,b
    {
      for ( j = 0; j < step_v; j++ )
      {
        for ( i = 0; i < step_h; i++ )
        {
#ifdef AVS2_S2_SBD
		  int bgr = 0;
#endif
		  for ( result = 0, x = -tap_min; x < tap_max; x++ )
          {
#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
			  if(background_reference_enable && img->num_of_references>=2 && ref_frame ==  img->num_of_references-1 && (img->type == P_IMG || img->type == F_IMG) && img->typeb != BP_IMG)
#else
			  if(input->profile_id == 0x50 && background_reference_enable && img->num_of_references>=2 && ref_frame ==  img->num_of_references-1 && img->type == P_IMG && img->typeb != BP_IMG)
#endif
			  {
				  result += background_frame[0][max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i + x ) ) ] * COEF[dx - 1][x + tap_min];
			  }
#ifdef AVS2_S2_S
#if AVS2_SCENE_CD
			  else if(img->typeb == BP_IMG)
#else
			  else if(input->profile_id == 0x50 && img->typeb == BP_IMG)
#endif
			  {
				  result += background_frame[0][max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i + x ) ) ] * COEF[dx - 1][x + tap_min];
			  }
#endif
			  else
			  {
				  result += ref_pic[max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i + x ) ) ] * COEF[dx - 1][x + tap_min];
			  }
#else
			result += ref_pic[max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i + x ) ) ] * COEF[dx - 1][x + tap_min];
#endif
          }

#if EXTEND_BD
      block[j][i] = max ( 0, min ( max_pel_value, ( result + (1 << (shift1 + shift2 - 1) ) ) >> (shift1 + shift2) ) );
#else
      block[j][i] = max ( 0, min ( max_pel_value, ( result + 32 ) >> 6 ) );
#endif
				}
      }
    }

    else if ( dx == 0 )   //vertical position: c,2,j
    {

      for ( j = 0; j < step_v; j++ )
      {
        for ( i = 0; i < step_h; i++ )
        {

#ifdef AVS2_S2_SBD
		  int bgr = 0;
#endif
		  for ( result = 0, y = -tap_min; y < tap_max; y++ )
          {
#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
			  if(background_reference_enable && img->num_of_references>=2 && ref_frame ==  img->num_of_references-1 && (img->type == P_IMG || img->type == F_IMG) && img->typeb != BP_IMG)
#else
			  if(input->profile_id == 0x50 && background_reference_enable && img->num_of_references>=2 && ref_frame ==  img->num_of_references-1 && img->type == P_IMG && img->typeb != BP_IMG)
#endif
			  {
				  result += background_frame[0][max ( 0, min ( maxold_y, y_pos + j + y ) ) ][max ( 0, min ( maxold_x, x_pos + i ) ) ] * COEF[dy - 1][y + tap_min];
			  }
#ifdef AVS2_S2_S
#if AVS2_SCENE_CD
			  else if(img->typeb == BP_IMG)
#else
			  else if(input->profile_id == 0x50 && img->typeb == BP_IMG)
#endif
			  {
				  result += background_frame[0][max ( 0, min ( maxold_y, y_pos + j + y ) ) ][max ( 0, min ( maxold_x, x_pos + i ) ) ] * COEF[dy - 1][y + tap_min];
			  }
#endif
			  else
			  {
				  result += ref_pic[max ( 0, min ( maxold_y, y_pos + j + y ) ) ][max ( 0, min ( maxold_x, x_pos + i ) ) ] * COEF[dy - 1][y + tap_min];
			  }
#else
			result += ref_pic[max ( 0, min ( maxold_y, y_pos + j + y ) ) ][max ( 0, min ( maxold_x, x_pos + i ) ) ] * COEF[dy - 1][y + tap_min];
#endif
          }
#if EXTEND_BD
      block[j][i] = max ( 0, min ( max_pel_value, ( result + (1 << (shift1 + shift2 - 1) ) ) >> (shift1 + shift2) ) );
#else
      block[j][i] = max ( 0, min ( max_pel_value, ( result + 32 ) >> 6 ) );
#endif
				}
      }
    }


    else   //vertical position: d,h,k; e,3,1; f,i,m
    {
      //interpolate horizontal a,1,b first

      for ( j = -3; j < step_v + 4; j++ )
      {
        for ( i = 0; i < step_h; i++ )
        {

#ifdef AVS2_S2_SBD
		  int bgr = 0;
#endif
		  for ( result = 0, x = -tap_min; x < tap_max; x++ )
          {
#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
			  if(background_reference_enable && img->num_of_references>=2 && ref_frame ==  img->num_of_references-1 && (img->type == P_IMG || img->type == F_IMG) && img->typeb != BP_IMG)
#else
			  if(input->profile_id == 0x50 && background_reference_enable && img->num_of_references>=2 && ref_frame ==  img->num_of_references-1 && img->type == P_IMG && img->typeb != BP_IMG)
#endif
			  {
				  result += background_frame[0][max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i + x ) ) ] * COEF[dx - 1][x + tap_min];
			  }
#ifdef AVS2_S2_S
#if AVS2_SCENE_CD
			  else if(img->typeb == BP_IMG)
#else
			  else if(input->profile_id == 0x50 && img->typeb == BP_IMG)
#endif
			  {
				  result += background_frame[0][max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i + x ) ) ] * COEF[dx - 1][x + tap_min];
			  }
#endif
			  else
        {
          result += ref_pic[max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i + x ) ) ] * COEF[dx - 1][x + tap_min];
        }
#else
            result += ref_pic[max ( 0, min ( maxold_y, y_pos + j ) ) ][max ( 0, min ( maxold_x, x_pos + i + x ) ) ] * COEF[dx - 1][x + tap_min];
#endif
      }
#if EXTEND_BD
      tmp_res[j + tap_min][i] = shift1 ? (result + (1 << (shift1 - 1))) >> shift1 : result;
#else
      tmp_res[j + tap_min][i] = result;
#endif
        }
      }

      //interpolate vertical d,h,k; e,3,1; f,i,m

      for ( j = 0; j < step_v; j++ )
      {
        for ( i = 0; i < step_h; i++ )
        {

#ifdef AVS2_S2_SBD
          int bgr = 0;
#endif
          for ( result = 0, y = -tap_min; y < tap_max; y++ )
          {

            result += tmp_res[j + tap_min + y][i] * COEF[dy - 1][y + tap_min];
          }

#if EXTEND_BD
          block[j][i] = max ( 0, min ( max_pel_value, ( result + ( 1 << (shift3 - 1)) ) >> shift3 ) );
#else
          block[j][i] = max ( 0, min ( max_pel_value, ( result + 2048 ) >> 12 ) );
#endif
        }
      }
    }
  }
}

/*
*************************************************************************
* Function:Reads the content of two successive startcode from the bitstream
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

int Header()
{
  unsigned char *Buf;
  int startcodepos, length;
  static unsigned long prev_pos = 0; // 08.16.2007
  int ext_ID;

  if ( ( Buf = ( char* ) calloc ( MAX_CODED_FRAME_SIZE , sizeof ( char ) ) ) == NULL )
  {
    no_mem_exit ( "GetAnnexbNALU: Buf" );
  }

  while ( 1 )
  {
    StartCodePosition = GetOneUnit ( Buf, &startcodepos, &length ); //jlzheng  7.5

    switch ( Buf[startcodepos] )
    {
    case SEQUENCE_HEADER_CODE:

      img->new_sequence_flag = 1;
      SequenceHeader ( Buf, startcodepos, length );
// Adaptive frequency weighting quantization  
#if FREQUENCY_WEIGHTING_QUANTIZATION
	  InitSeqQuantParam();
#endif

#if ALF
	  if (input->alf_enable && alfParAllcoated == 0)
	  {
		  CreateAlfGlobalBuffer();
		  alfParAllcoated = 1;
	  }
#if BUFFER_CLEAN
#if !ALF_BUFFER_OFF
	  {
		  int i, j;
		  for (i=0; i<MAX_NUM_APS; i++)
		  {
			  g_APSList[i].usedflag = 0;
			  g_APSList[i].cur_number = 0;
			  for (j=0; j<NUM_ALF_COMPONENT; j++)
			  {
				  g_APSList[i].alf_par[j].alf_flag = 0;
			  }
		  }
	  }
#endif
#endif
#endif

      img->seq_header_indicate = 1;
      break;
    case EXTENSION_START_CODE:
      extension_data ( Buf, startcodepos, length );
      break;
    case USER_DATA_START_CODE:
      user_data ( Buf, startcodepos, length );
      break;
    case VIDEO_EDIT_CODE:
      video_edit_code_data ( Buf, startcodepos, length );
      break;
    case I_PICTURE_START_CODE:
      I_Picture_Header ( Buf, startcodepos, length );
      calc_picture_distance ();

#if ALF
	    Read_ALF_param(Buf, startcodepos, length );	  
#endif

      if ( !img->seq_header_indicate )
      {
        img->B_discard_flag = 1;
        fprintf ( stdout, "    I   %3d\t\tDIDSCARD!!\n", img->tr );
        break;
      }

      break;
    case PB_PICTURE_START_CODE:
      PB_Picture_Header ( Buf, startcodepos, length );
      calc_picture_distance ();

#if ALF
	    Read_ALF_param(Buf, startcodepos, length );	  
#endif
      // xiaozhen zheng, 20071009
      if ( !img->seq_header_indicate )
      {
        img->B_discard_flag = 1;

        if ( img->type == P_IMG )
        {
          fprintf ( stdout, "    P   %3d\t\tDIDSCARD!!\n", img->tr );
        }
#if DHP
        if ( img->type == F_IMG )
        {
          fprintf ( stdout, "    F   %3d\t\tDIDSCARD!!\n", img->tr );
        }
#endif
        else
        {
          fprintf ( stdout, "    B   %3d\t\tDIDSCARD!!\n", img->tr );
        }

        break;
      }

      if ( img->seq_header_indicate == 1 && img->type != B_IMG )
      {
        img->B_discard_flag = 0;
      }
#if !M3475_RANDOM_ACCESS
      if ( img->type == B_IMG && img->B_discard_flag == 1 && !img->no_forward_reference )
#else 
      if ( img->type == B_IMG && img->B_discard_flag == 1 && !img->random_access_decodable_flag )
#endif 
      {
        fprintf ( stdout, "    B   %3d\t\tDIDSCARD!!\n", img->tr );
        break;
      }

      break;
    case SEQUENCE_END_CODE:
      img->new_sequence_flag = 1;
      img->sequence_end_flag = 1;
      free ( Buf );
      return EOS;
      break;
    default:

#if !M3475_RANDOM_ACCESS
      if ( ( Buf[startcodepos] >= SLICE_START_CODE_MIN && Buf[startcodepos] <= SLICE_START_CODE_MAX )
           && ( ( !img->seq_header_indicate ) || ( img->type == B_IMG && img->B_discard_flag == 1 && !img->no_forward_reference ) ) )
#else 
		if ( ( Buf[startcodepos] >= SLICE_START_CODE_MIN && Buf[startcodepos] <= SLICE_START_CODE_MAX )
			&& ( ( !img->seq_header_indicate ) || ( img->type == B_IMG && img->B_discard_flag == 1 && !img->random_access_decodable_flag ) ) )
#endif 
      {
        break;
      }
      else if ( Buf[startcodepos] >= SLICE_START_CODE_MIN )   // modified by jimmy 2009.04.01
      {
        if ( ( temp_slice_buf = ( char* ) calloc ( MAX_CODED_FRAME_SIZE , sizeof ( char ) ) ) == NULL ) // modified 08.16.2007
        {
          no_mem_exit ( "GetAnnexbNALU: Buf" );
        }

        first_slice_length = length;
        first_slice_startpos = startcodepos;
        memcpy ( temp_slice_buf, Buf, length );
        free ( Buf );
        return SOP;
      }
      else
      {
        printf ( "Can't find start code" );
        free ( Buf );
        return EOS;
      }
    }
  }

}

/*
*************************************************************************
* Function:Initializes the parameters for a new frame
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/


void init_frame ()
{
  static int first_P = TRUE;
  int i, j;

  for ( i = 0; i < img->width / ( MIN_BLOCK_SIZE ) + 1; i++ ) // set edge to -1, indicate nothing to predict from
  {
    img->ipredmode[0][i + 1] = -1;
    img->ipredmode[img->height / ( MIN_BLOCK_SIZE ) + 1][i + 1] = -1;
  }

  for ( j = 0; j < img->height / ( MIN_BLOCK_SIZE ) + 1; j++ )
  {
    img->ipredmode[j + 1][0] = -1;
    img->ipredmode[j + 1][img->width / ( MIN_BLOCK_SIZE ) + 1] = -1;
  }

  img->ipredmode    [0][0] = -1;

  for ( i = 0; i < img->max_mb_nr; i++ )
  {
    img->mb_data[i].slice_nr = -1;
  }

#if MULTIVIEW_CODING
  if( img->baseView_type == I_IMG && img->view_index > 0)
  {
	  curr_RPS.num_of_ref = 0;
	  curr_RPS.referd_by_others = 1;
  }
  prepare_RefInfo();
#else
#ifdef AVS2_S2_BGLONGTERM
	if(img->typeb == BACKGROUND_IMG && background_picture_output_flag == 0)
		currentFrame = background_ref;
	else
#endif
		prepare_RefInfo();
#endif

  imgY =  currentFrame[0];
  imgUV =  &currentFrame[1];

  // Adaptive frequency weighting quantization  
#if FREQUENCY_WEIGHTING_QUANTIZATION
  if(weight_quant_enable_flag&&pic_weight_quant_enable_flag)
  {
	  InitFrameQuantParam();
	  FrameUpdateWQMatrix();		//M2148 2007-09
  }
#endif

}

/*
*************************************************************************
* Function:decodes one picture
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void picture_data ()
{
  unsigned char *Buf;
  int startcodepos, length;
  const int mb_nr = img->current_mb_nr;
#if M3198_CU8
  int mb_width = img->width / MIN_CU_SIZE;
#else
  int mb_width = img->width / 16;
#endif
  int first_slice = 1; //08.16.2007 tianf
  int N8_SizeScale = 1 << ( input->g_uiMaxSizeInBit - MIN_CU_SIZE_IN_BIT );
  int j;
  int num_of_orgMB_in_row ;//4:1  5:2  6:4
  int num_of_orgMB_in_col ;
  int size = 1 << input->g_uiMaxSizeInBit;
  int pix_x = ( img->current_mb_nr % img->PicWidthInMbs ) << MIN_CU_SIZE_IN_BIT;
  int pix_y = ( img->current_mb_nr / img->PicWidthInMbs ) << MIN_CU_SIZE_IN_BIT;
  Slice *currSlice = img->currentSlice;      //lzhang for AEC
  int    ByteStartPosition;
  int    i;
  int    new_slice = 0;
  int    smb_index;
#if ALF
#if !ALF_BUFFER_OFF
  Boolean isNewApsSent;
#endif
  Boolean currAlfEnable;
  DataPartition *dP;
  int compIdx,ctx_idx;
  int img_height,img_width,lcuHeight,lcuWidth,numLCUInPicWidth,numLCUInPicHeight,NumCUInFrame;
#endif
  Boolean   aec_mb_stuffing_bit;
  img->current_slice_nr = -1;                 // jlzheng 6.30
  currentbitoffset = currStream->frame_bitoffset;   // jlzheng 6.30
  currStream->frame_bitoffset = 0;                  // jlzheng 6.30

  if ( ( Buf = ( char* ) calloc ( MAX_CODED_FRAME_SIZE , sizeof ( char ) ) ) == NULL )
  {
    no_mem_exit ( "GetAnnexbNALU: Buf" );  //jlzheng  6.30
  }

  smb_index = 0;
#if ALF
  lcuHeight         = 1<<input->g_uiMaxSizeInBit;
  lcuWidth          = lcuHeight;
  img_height        = img->height;
  img_width         = img->width;
  numLCUInPicWidth  = img_width / lcuWidth ;
  numLCUInPicHeight = img_height / lcuHeight ;
  numLCUInPicWidth  += (img_width % lcuWidth)? 1 : 0;
  numLCUInPicHeight += (img_height % lcuHeight)? 1 : 0;
  NumCUInFrame = numLCUInPicHeight * numLCUInPicWidth;
  g_MaxSizeInbit = input->g_uiMaxSizeInBit;
#endif
  while ( img->current_mb_nr < img->PicSizeInMbs ) // loop over super codingUnits
  {
    //decode slice header   jlzheng 6.30
#if LCUBASE_SLICE
	if ( img->current_mb_nr < img->PicSizeInMbs ) // check every LCU
#else
    if ( input->slice_set_enable || ( !input->slice_set_enable && ( img->current_mb_nr % ( ( 1 << ( input->g_uiMaxSizeInBit - MIN_CU_SIZE_IN_BIT ) ) *mb_width ) == 0 ) ) ) //modified by mz, 2008.04
#endif
    {
      if ( first_slice )
      {
        SliceHeader ( temp_slice_buf, first_slice_startpos, first_slice_length );
        free ( temp_slice_buf );
        img->current_slice_nr++;
        first_slice = 0;
        new_slice = 1;
      }
      else
      {
        if ( checkstartcode() )
        {
          GetOneUnit ( Buf, &startcodepos, &length );
          StatBitsPtr->curr_frame_bits += length;
          SliceHeader ( Buf, startcodepos, length );
          img->current_slice_nr++;
          new_slice = 1;
        }
        else
        {
          new_slice = 0;
        }
      }

      if ( new_slice )
      {

        init_contexts ();
        AEC_new_slice();
        ByteStartPosition = ( currStream->frame_bitoffset ) / 8;


        for ( i = 0; i < 1; i++ )
        {
          img->currentSlice->partArr[i].readSyntaxElement = readSyntaxElement_AEC;
          img->currentSlice->partArr[i].bitstream = currStream ;
        }

        currStream = currSlice->partArr[0].bitstream;

        if ( ( currStream->frame_bitoffset ) % 8 != 0 )
        {
          ByteStartPosition++;
        }

        arideco_start_decoding ( &img->currentSlice->partArr[0].de_AEC, currStream->streamBuffer, ( ByteStartPosition ), & ( currStream->read_len ), img->type );
      }
    }  //decode slice header


    pix_x = ( img->current_mb_nr % img->PicWidthInMbs ) << MIN_CU_SIZE_IN_BIT;
    pix_y = ( img->current_mb_nr / img->PicWidthInMbs ) << MIN_CU_SIZE_IN_BIT;
    num_of_orgMB_in_col = N8_SizeScale;
    num_of_orgMB_in_row = N8_SizeScale;

    if ( pix_x + size >= img->width )
    {
      num_of_orgMB_in_col = ( img->width - pix_x ) >> MIN_CU_SIZE_IN_BIT;
    }

    if ( pix_y + size >= img->height )
    {
      num_of_orgMB_in_row = ( img->height - pix_y ) >> MIN_CU_SIZE_IN_BIT;
    }

    for ( i = 0; i < num_of_orgMB_in_row; i++ )
    {
      int pos = img->current_mb_nr + i * img->PicWidthInMbs;

      for ( j = 0; j < num_of_orgMB_in_col; j++, pos++ )
      {
        img->mb_data[pos].slice_nr = img->current_slice_nr;
      }
    }

#if TRACE
    fprintf ( p_trace, "\n*********** Pic: %i (I/P) MB: %i Slice: %i Type %d **********\n", img->tr, img->current_mb_nr, img->current_slice_nr, img->type );
#endif
    start_codingUnit ( input->g_uiMaxSizeInBit );
#if ALF
#if MULTIVIEW_CODING
	if (input->sao_enable && !img->bDepth)
#else
	if (input->sao_enable)
#endif
	{
#if SAO_CROSS_SLICE_FLAG
		sao_cross_slice = input->crossSliceLoopFilter;
#endif
		readParaSAO_one_SMB(smb_index, pix_y >> MIN_CU_SIZE_IN_BIT, pix_x >> MIN_CU_SIZE_IN_BIT,  num_of_orgMB_in_col, num_of_orgMB_in_row, img->slice_sao_on, img->saoBlkParams[smb_index], img->rec_saoBlkParams[smb_index]);	
	}
#if MULTIVIEW_CODING
	if (input->alf_enable)	
#else
	if (input->alf_enable)
#endif
	{
		dP = &(currSlice->partArr[0]);
		for (compIdx=0;compIdx<NUM_ALF_COMPONENT;compIdx++)
		{
			if (img->pic_alf_on[compIdx])
			{
#if !M3544_CONTEXT_OPT
				ctx_idx = getLCUCtrCtx_Idx(smb_index,numLCUInPicWidth,numLCUInPicHeight,NumCUInFrame,compIdx,Dec_ALF->m_AlfLCUEnabled);
#else 
                ctx_idx =  0;
#endif
				Dec_ALF->m_AlfLCUEnabled[smb_index][compIdx] = readAlfLCUCtrl(img,&(dP->de_AEC),compIdx,ctx_idx);
			}
			else
			{
				Dec_ALF->m_AlfLCUEnabled[smb_index][compIdx] = FALSE;
			}
		}
	}
	if (input->sao_enable || input->alf_enable)
	{
		smb_index++;
	}
	decode_SMB ( input->g_uiMaxSizeInBit, img->current_mb_nr );
#else
	if (input->sao_enable)
	{
		readParaSAO_one_SMB(smb_index, pix_y >> MIN_CU_SIZE_IN_BIT, pix_x >> MIN_CU_SIZE_IN_BIT,  num_of_orgMB_in_col, num_of_orgMB_in_row, img->slice_sao_on, img->saoBlkParams[smb_index], img->rec_saoBlkParams[smb_index]);
		smb_index++;
	}
	decode_SMB ( input->g_uiMaxSizeInBit, img->current_mb_nr );
#endif
    if ( img->current_mb_nr % img->PicWidthInMbs + N8_SizeScale >= img->PicWidthInMbs )
    {
      if ( img->current_mb_nr / img->PicWidthInMbs + N8_SizeScale >= img->PicHeightInMbs )
      {
        img->current_mb_nr = img->max_mb_nr;
      }
      else
      {
        img->current_mb_nr = ( img->current_mb_nr / img->PicWidthInMbs + N8_SizeScale ) * img->PicWidthInMbs;
      }
    }
    else
    {
      img->current_mb_nr = img->current_mb_nr + N8_SizeScale;
    }

    aec_mb_stuffing_bit = AEC_startcode_follows ( 1 );
  }

  free ( Buf );

#if MULTIVIEW_CODING
  if ( !loop_filter_disable && !img->bDepth)
#else
  if ( !loop_filter_disable )
#endif
  {
	  CreateEdgeFilter();
	  SetEdgeFilter(); 
	  DeblockFrame ( imgY, imgUV );
  }
#if MULTIVIEW_CODING
  if (input->sao_enable && !img->bDepth)
#else
  if (input->sao_enable)
#endif
  {
	  Copy_frame_for_SAO();
#if EXTEND_BD
	  SAOFrame(input->g_uiMaxSizeInBit, input->slice_set_enable, img->rec_saoBlkParams, img->slice_sao_on, input->sample_bit_depth);
#else
      SAOFrame(input->g_uiMaxSizeInBit, input->slice_set_enable, img->rec_saoBlkParams, img->slice_sao_on);
#endif
	}
#if ALF
#if MULTIVIEW_CODING
  if (input->alf_enable && !img->bDepth)
#else
  if (input->alf_enable)
#endif
  {	 
#if !ALF_BUFFER_OFF
	  isNewApsSent = (Boolean)img->pic_alf_apsNewflag;
#endif
	  currAlfEnable = !(Dec_ALF->m_alfPictureParam[ALF_Y]->alf_flag==0 && Dec_ALF->m_alfPictureParam[ALF_Cb]->alf_flag==0 && Dec_ALF->m_alfPictureParam[ALF_Cr]->alf_flag==0 );

	  if (currAlfEnable)
	  {
		  Copy_frame_for_ALF();
#if EXTEND_BD
          ALFProcess_dec(Dec_ALF->m_alfPictureParam,img,imgY_alf_Rec,imgUV_alf_Rec, input->sample_bit_depth);
#else
          ALFProcess_dec(Dec_ALF->m_alfPictureParam,img,imgY_alf_Rec,imgUV_alf_Rec);
#endif

	  }	
  }
#endif
#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
  if((img->type == P_IMG || img->type == F_IMG) && background_picture_enable && background_reference_enable)
#else
  if(img->type == P_IMG && background_picture_enable && background_reference_enable && input->profile_id == 0x50)
#endif
  {
	  int j,i;
#if !M3476_BUF_FIX
	  for(j = 0; j < img->height/8; j++)
		  for(i = 0; i < img->width/8; i++)
#else 
	  for(j = 0; j < img->height/MIN_BLOCK_SIZE; j++)
		  for(i = 0; i < img->width/MIN_BLOCK_SIZE; i++)
#endif
		  {
			  int refframe  = refFrArr[j][i];
			  if(refframe==img->num_of_references-1)
				  refFrArr[j][i] = -1;
		  }
  }
#endif
}
#if ALF
void Copy_frame_for_ALF()
{
	int i, j, k;

	for (j = 0; j < img->height; j++)
	{
		for ( i = 0; i< img->width; i++)
		{
			imgY_alf_Rec[j*(img->width)+i] = imgY[j][i];
		}
	}

	for (k = 0; k < 2; k++)
	{
		for (j = 0; j < img->height_cr; j++)
		{
			for ( i = 0; i< img->width_cr; i++)
			{
				imgUV_alf_Rec[k][j*(img->width_cr)+i] = imgUV[k][j][i];
			}
		}
	}
}
#endif

#if !MULTIVIEW_CODING
void min_tr( outdata data, int* pos)
{
	int i,tmp_min;
	tmp_min = data.stdoutdata[0].tr;
	*pos = 0;
	for ( i=1; i<data.buffer_num; i++)
	{
		if (data.stdoutdata[i].tr<tmp_min)
		{
			tmp_min = data.stdoutdata[i].tr;
			*pos = i;
		}
	}
}
void delete_trbuffer( outdata *data, int pos)
{
	int i;
	for ( i=pos; i< data->buffer_num-1; i++ )
	{
		data->stdoutdata[i] = data->stdoutdata[i+1];
	}
	data->buffer_num--;
}
void addCurrMvtoBuf()
{
	int i, k, x, y;
	for ( i=0; i<REF_MAXBUFFER; i++ )
	{
		if ( img->coding_order == img->imgcoi_ref[i] )
		{
			break;
		}
	}
	for ( k = 0; k < 2; k++ )
	{
		for ( y = 0; y < img->height / MIN_BLOCK_SIZE; y++ )
		{
			for ( x = 0; x < img->width / MIN_BLOCK_SIZE ; x++ )
			{
#if DHP
				mvbuf[i][y][x][k] = (((img->type==F_IMG)||(img->type==P_IMG))? img->tmp_mv:img->fw_mv)[y][x][k];
#else
				mvbuf[i][y][x][k] = (img->type==P_IMG? img->tmp_mv:img->fw_mv)[y][x][k];
#endif
			}
		}
	}
	for ( y = 0; y < img->height / MIN_BLOCK_SIZE; y++ )
	{
		for ( x = 0; x < img->width / MIN_BLOCK_SIZE ; x++ )
		{
#if DHP
			refbuf[i][y][x] = (((img->type==F_IMG)||(img->type==P_IMG))? refFrArr:img->fw_refFrArr)[y][x];
#else
			refbuf[i][y][x] = (img->type==P_IMG? refFrArr:img->fw_refFrArr)[y][x];
#endif
		}
	}
}
#endif


// Sub-sampling of the stored reference index and motion vector
#if MV_COMPRESSION

void compressMotion()
{
	int i, k, x, y;
	int width = img->width;
	int height = img->height;
	int xPos, yPos;

	for ( i=0; i<REF_MAXBUFFER; i++ )
	{
		if ( img->coding_order == img->imgcoi_ref[i] )
		{
			break;
		}
	}

	for (y = 0; y < height / MIN_BLOCK_SIZE; y ++)
	{
		for (x = 0; x < width / MIN_BLOCK_SIZE; x ++)
		{
			yPos = y / MV_DECIMATION_FACTOR * MV_DECIMATION_FACTOR + 2;
			xPos = x / MV_DECIMATION_FACTOR * MV_DECIMATION_FACTOR + 2;

			if(yPos >= height / MIN_BLOCK_SIZE){
				yPos = (y / MV_DECIMATION_FACTOR * MV_DECIMATION_FACTOR + height / MIN_BLOCK_SIZE) / 2;
			}
			if(xPos >= width / MIN_BLOCK_SIZE){
				xPos = (x / MV_DECIMATION_FACTOR * MV_DECIMATION_FACTOR + width / MIN_BLOCK_SIZE) / 2;
			}
			mvbuf[i][y][x][0] = mvbuf[i][yPos][xPos][0];
			mvbuf[i][y][x][1] = mvbuf[i][yPos][xPos][1];
			refbuf[i][y][x] = refbuf[i][yPos][xPos];		
		}
	}
}
#endif
/*
*************************************************************************
* Function:Prepare field and frame buffer after frame decoding
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

#if MULTIVIEW_CODING
void frame_postprocessing (SNRParameters *snr )
{
	//pic dist by Grandview Semi. @ [06-07-20 15:25]
	img->multiView_PrevPicDistanceLsb[img->view_index] = (img->coding_order % 256);
	if ( p_ref && !input->ref_pic_order )
	{
#ifdef AVS2_S2_BGLONGTERM
		if(img->typeb == BACKGROUND_IMG && background_picture_output_flag==0)
			find_snr_background( snr, p_ref_background);
		else
#endif
			find_snr ( snr, p_ref ); // if ref sequence exist
	}
	{
#if MULTIVIEW_CODING
		int pointer_tmp = outprint.buffer_num[img->view_index];
#else
		int pointer_tmp = outprint.buffer_num;
#endif
		int i,pos;
#if MULTIVIEW_CODING
		outprint.stdoutdata[img->view_index][pointer_tmp].type = img->type;
#ifdef AVS2_S2_BGLONGTERM
		outprint.stdoutdata[img->view_index][pointer_tmp].typeb = img->typeb;
#endif
		outprint.stdoutdata[img->view_index][pointer_tmp].framenum = img->tr;
		outprint.stdoutdata[img->view_index][pointer_tmp].tr = img->tr;
		outprint.stdoutdata[img->view_index][pointer_tmp].qp = img->qp;
		outprint.stdoutdata[img->view_index][pointer_tmp].snr_y = snr->snr_y;
		outprint.stdoutdata[img->view_index][pointer_tmp].snr_u = snr->snr_u;
		outprint.stdoutdata[img->view_index][pointer_tmp].snr_v = snr->snr_v;
		outprint.stdoutdata[img->view_index][pointer_tmp].tmp_time = tmp_time;
		outprint.stdoutdata[img->view_index][pointer_tmp].picture_structure = img->picture_structure;
		outprint.stdoutdata[img->view_index][pointer_tmp].curr_frame_bits = StatBitsPtr->curr_frame_bits;
		outprint.stdoutdata[img->view_index][pointer_tmp].emulate_bits = StatBitsPtr->emulate_bits;
		outprint.buffer_num[img->view_index]++;
#else
		outprint.stdoutdata[pointer_tmp].type = img->type;
#ifdef AVS2_S2_BGLONGTERM
		outprint.stdoutdata[pointer_tmp].typeb = img->typeb;
#endif
		outprint.stdoutdata[pointer_tmp].framenum = img->tr;
		outprint.stdoutdata[pointer_tmp].tr = img->tr;
		outprint.stdoutdata[pointer_tmp].qp = img->qp;
		outprint.stdoutdata[pointer_tmp].snr_y = snr->snr_y;
		outprint.stdoutdata[pointer_tmp].snr_u = snr->snr_u;
		outprint.stdoutdata[pointer_tmp].snr_v = snr->snr_v;
		outprint.stdoutdata[pointer_tmp].tmp_time = tmp_time;
		outprint.stdoutdata[pointer_tmp].picture_structure = img->picture_structure;
		outprint.stdoutdata[pointer_tmp].curr_frame_bits = StatBitsPtr->curr_frame_bits;
		outprint.stdoutdata[pointer_tmp].emulate_bits = StatBitsPtr->emulate_bits;
		outprint.buffer_num++;
#endif

#if !MULTIVIEW_CODING
		if (curr_RPS.referd_by_others && img->type!=I_IMG )
#endif
		{
			addCurrMvtoBuf();
#if MV_COMPRESSION
			if (curr_RPS.referd_by_others && img->type!=I_IMG )
				compressMotion();
#endif
		}

#ifdef AVS2_S2_BGLONGTERM

#if AVS2_SCENE_GB_CD
#else
		if(img->typeb == BACKGROUND_IMG && background_picture_output_flag==0)
		{
			write_GB_frame(p_out_background);
			report_frame( outprint, 0 );
			delete_trbuffer( & outprint, 0 );
		}
		else
#endif

#endif
#if MULTIVIEW_CODING
#if !REF_OUTPUT
			for ( i=0; i< outprint.buffer_num[img->view_index]; i++)
			{
				min_tr(outprint,&pos);
				if ( outprint.stdoutdata[img->view_index][pos].tr < img->tr ||  outprint.stdoutdata[img->view_index][pos].tr == (last_output+1) )
				{
					last_output = outprint.stdoutdata[img->view_index][pos].tr;
					report_frame( outprint, pos );
					write_frame( p_out, outprint.stdoutdata[img->view_index][pos].tr );
					delete_trbuffer( &outprint, pos );
					i--;
				}
				else
				{
					break;
				}
			}
#else 
			if (img->coding_order+total_frames*256>= picture_reorder_delay )
			{

				int tmp_min,pos=-1;
				tmp_min = 1<<20;

				for ( i=0; i<outprint.buffer_num[img->view_index]; i++)
				{

					if (outprint.stdoutdata[img->view_index][i].tr<tmp_min && outprint.stdoutdata[img->view_index][i].tr>multiView_last_output[img->view_index])
					{
						pos=i;
						tmp_min=outprint.stdoutdata[img->view_index][i].tr;

					}
				}
				if (pos!=-1)
				{

					multiView_last_output[img->view_index] = outprint.stdoutdata[img->view_index][pos].tr;

					report_frame( outprint, pos );
					write_frame( p_out, outprint.stdoutdata[img->view_index][pos].tr );
					delete_trbuffer( &outprint, pos );

				}

			}
#endif
#else
#if !REF_OUTPUT
			for ( i=0; i< outprint.buffer_num; i++)
			{
				min_tr(outprint,&pos);
				if ( outprint.stdoutdata[pos].tr < img->tr ||  outprint.stdoutdata[pos].tr == (last_output+1) )
				{
					last_output = outprint.stdoutdata[pos].tr;
					report_frame( outprint, pos );
					write_frame( p_out, outprint.stdoutdata[pos].tr );
					delete_trbuffer( &outprint, pos );
					i--;
				}
				else
				{
					break;
				}
			}
#else 
			if (img->coding_order>= picture_reorder_delay )
			{

				int tmp_min,pos=-1;
				tmp_min = 1<<20;

				for ( i=0; i<outprint.buffer_num; i++)
				{
#if AVS2_SCENE_GB_CD
					if (outprint.stdoutdata[i].tr<tmp_min && outprint.stdoutdata[i].tr>=last_output) //GB has the same "tr" with "last_output"
#else
					if (outprint.stdoutdata[i].tr<tmp_min && outprint.stdoutdata[i].tr>last_output)
#endif
					{
						pos=i;
						tmp_min=outprint.stdoutdata[i].tr;

					}
				}
				if (pos!=-1)
				{
					last_output = outprint.stdoutdata[pos].tr;
					report_frame( outprint, pos );
#if AVS2_SCENE_GB_CD
					if(outprint.stdoutdata[pos].typeb == BACKGROUND_IMG && background_picture_output_flag == 0)
						write_GB_frame( p_out_background );
					else
#endif
						write_frame( p_out, outprint.stdoutdata[pos].tr );
					delete_trbuffer( &outprint, pos );

				}

			}
#endif 
#endif
	}
}
#else
void frame_postprocessing ()
{
  //pic dist by Grandview Semi. @ [06-07-20 15:25]
	img->PrevPicDistanceLsb = (img->coding_order%256);
  if ( p_ref && !input->ref_pic_order )
  {
#ifdef AVS2_S2_BGLONGTERM
	  if(img->typeb == BACKGROUND_IMG && background_picture_output_flag==0)
		  find_snr_background( snr, p_ref_background);
	  else
#endif
		find_snr ( snr, p_ref ); // if ref sequence exist
  }
  {
	  int pointer_tmp = outprint.buffer_num;
	  int i,pos;
	  outprint.stdoutdata[pointer_tmp].type = img->type;
#ifdef AVS2_S2_BGLONGTERM
	  outprint.stdoutdata[pointer_tmp].typeb = img->typeb;
#endif
	  outprint.stdoutdata[pointer_tmp].framenum = img->tr;
	  outprint.stdoutdata[pointer_tmp].tr = img->tr;
	  outprint.stdoutdata[pointer_tmp].qp = img->qp;
	  outprint.stdoutdata[pointer_tmp].snr_y = snr->snr_y;
	  outprint.stdoutdata[pointer_tmp].snr_u = snr->snr_u;
	  outprint.stdoutdata[pointer_tmp].snr_v = snr->snr_v;
	  outprint.stdoutdata[pointer_tmp].tmp_time = tmp_time;
	  outprint.stdoutdata[pointer_tmp].picture_structure = img->picture_structure;
	  outprint.stdoutdata[pointer_tmp].curr_frame_bits = StatBitsPtr->curr_frame_bits;
	  outprint.stdoutdata[pointer_tmp].emulate_bits = StatBitsPtr->emulate_bits;
	  outprint.buffer_num++;

	  if (curr_RPS.referd_by_others && img->type!=I_IMG )
	  {
		  addCurrMvtoBuf();
#if MV_COMPRESSION
          compressMotion();
#endif
	  }

#ifdef AVS2_S2_BGLONGTERM

#if AVS2_SCENE_GB_CD
#else
	  if(img->typeb == BACKGROUND_IMG && background_picture_output_flag==0)
	  {
		  write_GB_frame(p_out_background);
		  report_frame( outprint, 0 );
		  delete_trbuffer( & outprint, 0 );
	  }
	  else
#endif

#endif
#if !REF_OUTPUT
		  for ( i=0; i< outprint.buffer_num; i++)
		  {
			  min_tr(outprint,&pos);
			  if ( outprint.stdoutdata[pos].tr < img->tr ||  outprint.stdoutdata[pos].tr == (last_output+1) )
			  {
				  last_output = outprint.stdoutdata[pos].tr;
				  report_frame( outprint, pos );
				  write_frame( p_out, outprint.stdoutdata[pos].tr );
				  delete_trbuffer( &outprint, pos );
				  i--;
			  }
			  else
			  {
				  break;
			  }
		  }
#else 
#if REF_MINUS
		  if (img->coding_order+total_frames*256>= picture_reorder_delay )
#else
		  if (img->coding_order>= picture_reorder_delay )
#endif
		  {

			  int tmp_min,pos=-1;
			  tmp_min = 1<<20;

			  for ( i=0; i<outprint.buffer_num; i++)
			  {
#if AVS2_SCENE_GB_CD
				  if (outprint.stdoutdata[i].tr<tmp_min && outprint.stdoutdata[i].tr>=last_output) //GB has the same "tr" with "last_output"
#else
				  if (outprint.stdoutdata[i].tr<tmp_min && outprint.stdoutdata[i].tr>last_output)
#endif
				  {
					  pos=i;
					  tmp_min=outprint.stdoutdata[i].tr;

				  }
			  }
			  if (pos!=-1)
			  {
				  last_output = outprint.stdoutdata[pos].tr;
				  report_frame( outprint, pos );
#if AVS2_SCENE_GB_CD
				  if(outprint.stdoutdata[pos].typeb == BACKGROUND_IMG && background_picture_output_flag == 0)
					  write_GB_frame( p_out_background );
				  else
#endif
				  write_frame( p_out, outprint.stdoutdata[pos].tr );
				  delete_trbuffer( &outprint, pos );

			  }

		  }
#endif 
  }
}

#endif
/*
******************************************************************************
*  Function: Determine the MVD's value (1/4 pixel) is legal or not.
*  Input:
*  Output:
*  Return:   0: out of the legal mv range; 1: in the legal mv range
*  Attention:
*  Author: Xiaozhen ZHENG, rm52k
******************************************************************************
*/
void DecideMvRange()
{
#ifdef AVS2_S2_BGLONGTERM
#if EXTEND_BD
	if ( input->profile_id == BASELINE_PROFILE || input->profile_id == BASELINE10_PROFILE )
#else
	if ( input->profile_id == 0x20 || input->profile_id == 0x40 || input->profile_id == 0x50 )
#endif
#else
#if EXTEND_BD
	if ( input->profile_id == 0x20 || input->profile_id == 0x40 || input->profile_id == 0x52 )
#else
  if ( input->profile_id == 0x20 || input->profile_id == 0x40 )
#endif
#endif
  {
    switch ( input->level_id )
    {
    case 0x10:
      Min_V_MV = -512;
      Max_V_MV =  511;
      Min_H_MV = -8192;
      Max_H_MV =  8191;
      break;
    case 0x20:

      if ( img->picture_structure )
      {
        Min_V_MV = -1024;
        Max_V_MV =  1023;
      }

      Min_H_MV = -8192;
      Max_H_MV =  8191;
      break;
    case 0x22:

      if ( img->picture_structure )
      {
        Min_V_MV = -1024;
        Max_V_MV =  1023;
      }

      Min_H_MV = -8192;
      Max_H_MV =  8191;
      break;
    case 0x40:

      if ( img->picture_structure )
      {
        Min_V_MV = -2048;
        Max_V_MV =  2047;
      }

      Min_H_MV = -8192;
      Max_H_MV =  8191;
      break;
    case 0x42:

      if ( img->picture_structure )
      {
        Min_V_MV = -2048;
        Max_V_MV =  2047;
      }

      Min_H_MV = -8192;
      Max_H_MV =  8191;
      break;
    }
  }
}

#if MULTIVIEW_CODING
int  multiView_decode_one_frame ( SNRParameters *snr )
{
	int i,j, k;

	// the view number
	//const int viewNumber = input->view_number;

	int endFlag;
	//viewNumber = 1;

	for( i = 0; i < input->view_number; i++)
	{

		for ( j = 0; j<REF_MAXBUFFER; j++)
		{
			//set the reference frame pixel address of ith view to ref
			ref[j]			= multiView_ref[i][j];
			// set the poc of reference frames in ith view to imgtr_fwRefDistance
			img->imgtr_fwRefDistance[j] = img->multiView_imgtr_fwRefDistance[i][j];
			//set the coding order index of each reference frames in ith view to the image
			img->imgcoi_ref[j]   		= img->multiView_imgcoi_ref[i][j];
			// indicate whether each frame is refered by other frames
			img->refered_by_others[j]	= img->multiView_refered_by_others[i][j];
			//ref_poc: the reference frame of the reference frames
			memcpy(ref_poc[j], multiView_ref_poc[i][j], 4*sizeof(int));

			if (saorate[j])
			{
				for (k=0; k<3; k++)
				{
					saorate[j][k]			= multiView_saorate[i][j][k];
				}
			}

			//set the reference frame MV address of ith view to mvbuf
			mvbuf[j]        = multiView_mvbuf[i][j];
			//set the reference frame index address of ith view to refbuf
			refbuf[j]       = multiView_refbuf[i][j];

			img->is_output[j] = img->multiView_is_output[i][j];
		}

		// the reference frame index of each macroblock in current frame
		refFrArr = multiView_refFrArr[i];
		// mv of current F or P frame
		img->tmp_mv = img->multiView_tmp_mv[i];
		// forward mv of current B frame
		img->fw_mv  = img->multiView_fw_mv[i];
		// backward mv of current B frame
		img->bw_mv  = img->multiView_bw_mv[i];

		img->fw_refFrArr= img->multiView_fw_refFrArr[i];
		img->bw_refFrArr= img->multiView_bw_refFrArr[i];



		// set view index to image view index
		img -> view_index = i;

		//set whether the current image is depth image 
		img -> bDepth = 0;


		//the reconstruction file of the encoder
		p_ref = p_multiView_ref[i];
		//the reconstruction file of the decoder
		p_out = p_multiView_out[i];


		last_output = multiView_last_output[i];
		img->cur_saorate= img->multiView_cur_saorate[i];

		snr = &multiView_snrs[i];
		StatBitsPtr = &multiView_StatBits[i];

		endFlag = decode_one_frame (snr );

		// if find the end of sequence flag, return
		if(endFlag == EOS)
		{
			return EOS;
		}

		//the pointer of current view has changed, now update the pointer of the multiview

		for (j=0; j<REF_MAXBUFFER; j++)
		{
			multiView_ref[i][j] = ref[j];
			multiView_mvbuf[i][j] = mvbuf[j];
			multiView_refbuf[i][j] = refbuf[j];

			img->multiView_imgtr_fwRefDistance[i][j] = img->imgtr_fwRefDistance[j];
			img->multiView_imgcoi_ref[i][j] = img->imgcoi_ref[j];
			img->multiView_refered_by_others[i][j] = img->refered_by_others[j];
			memcpy(multiView_ref_poc[i][j], ref_poc[j], 4*sizeof(int));

			for (k=0; k<3; k++)
			{
				multiView_saorate[i][j][k]	    	 = saorate[j][k];
			}

			img->multiView_is_output[i][j] = img->is_output[j];
		}

		img->multiView_tmp_mv[i] = img->tmp_mv;
		img->multiView_fw_mv[i]  = img->fw_mv;
		img->multiView_bw_mv[i]  = img->bw_mv;

		img->multiView_fw_refFrArr[i] = img->fw_refFrArr;
		img->multiView_bw_refFrArr[i] = img->bw_refFrArr;

		//for depth
		// loop the every frame in different views at the same access unit

		if(input->bUseDepth == 1)
		{
			// loop all reference frames
			for ( j = 0; j<REF_MAXBUFFER; j++)
			{

				//set the reference frame pixel address of ith view to ref
				ref[j]          = multiView_depth_ref[i][j];
				// set the poc of reference frames in ith view to imgtr_fwRefDistance
				img->imgtr_fwRefDistance[j] = img->multiView_depth_imgtr_fwRefDistance[i][j];
				//set the coding order index of each reference frames in ith view to the image
				img->imgcoi_ref[j]   		= img->multiView_depth_imgcoi_ref[i][j];
				// indicate whether each frame is refered by other frames
				img->refered_by_others[j]	= img->multiView_depth_refered_by_others[i][j];


				if (saorate[j])
				{
					for (k=0; k<3; k++)
					{
						saorate[j][k]			= multiView_depth_saorate[i][j][k];
					}
				}
				//ref_poc: the reference frame of the reference frames
				memcpy(ref_poc[j], multiView_depth_ref_poc[i][j], 4*sizeof(int));


				//set the reference frame MV address of ith view to mvbuf
				mvbuf[j]        = multiView_depth_mvbuf[i][j];
				//set the reference frame index address of ith view to refbuf
				refbuf[j]       = multiView_depth_refbuf[i][j];
				//set the reference frame upsampled pixel address of ith view to oneForthRefY
				img->is_output[j] = img->multiView_depth_is_ouput[i][j];
			}

			//// the reference frame index of each macroblock in current frame
			refFrArr = multiView_depth_refFrArr[i];
			// mv of current F or P frame
			img->tmp_mv = img->multiView_depth_tmp_mv[i];
			// forward mv of current B frame
			img->fw_mv  = img->multiView_depth_fw_mv[i];
			// backward mv of current B frame
			img->bw_mv  = img->multiView_depth_bw_mv[i];

			img->fw_refFrArr= img->multiView_depth_fw_refFrArr[i];
			img->bw_refFrArr= img->multiView_depth_bw_refFrArr[i];


			// set view index to image view index
			img -> view_index = i;

			//set the type of video 
			img -> bDepth = 1;

			//the reconstruction file of the encoder
			p_ref = p_depth_multiView_ref[i];
			//the reconstruction file of the decoder
			p_out = p_depth_multiView_out[i];

			img->cur_saorate= img->multiView_depth_cur_saorate[i];

			snr = &multiView_depth_snrs[i];
			StatBitsPtr = &multiView_depth_StatBits[i];

			endFlag = decode_one_frame (snr );

			// if find the end of sequence flag, return
			if(endFlag == EOS)
			{
				return EOS;
			}

			//the pointer of current view has changed, now update the pointer of the multiview

			for (j=0; j<REF_MAXBUFFER; j++)
			{
				multiView_depth_ref[i][j] = ref[j];
				multiView_depth_mvbuf[i][j] = mvbuf[j];
				multiView_depth_refbuf[i][j] = refbuf[j];

				img->multiView_depth_imgtr_fwRefDistance[i][j] = img->imgtr_fwRefDistance[j];
				img->multiView_depth_imgcoi_ref[i][j]			 = img->imgcoi_ref[j];

				for (k=0; k<3; k++)
				{
					multiView_depth_saorate[i][j][k]	    	 = saorate[j][k];
				}

				img->multiView_depth_refered_by_others[i][j]   = img->refered_by_others[j];
				memcpy(multiView_depth_ref_poc[i][j], ref_poc[j], 4*sizeof(int));
			
				img->multiView_depth_is_ouput[i][j] = img->is_output[j];
			}


			img->multiView_depth_tmp_mv[i] = img->tmp_mv;
			img->multiView_depth_fw_mv[i]  = img->fw_mv;
			img->multiView_depth_bw_mv[i]  = img->bw_mv;

			img->multiView_depth_fw_refFrArr[i] = img->fw_refFrArr;
			img->multiView_depth_bw_refFrArr[i] = img->bw_refFrArr;
		}
	}

	return endFlag;
}

void depth_min_tr( outdata data, int* pos)
{
	int i,tmp_min;
	tmp_min = data.depth_stdoutdata[img->view_index][0].tr;
	*pos = 0;
	for ( i=1; i<data.depth_buffer_num[img->view_index]; i++)
	{
		if (data.depth_stdoutdata[img->view_index][i].tr<tmp_min)
		{
			tmp_min = data.depth_stdoutdata[img->view_index][i].tr;
			*pos = i;
		}
	}
}
void depth_delete_trbuffer( outdata *data, int pos)
{
	int i;
	for ( i=pos; i< data->depth_buffer_num[img->view_index]-1; i++ )
	{
		data->depth_stdoutdata[img->view_index][i] = data->depth_stdoutdata[img->view_index][i+1];
	}
	data->depth_buffer_num[img->view_index]--;
}
void min_tr( outdata data, int* pos)
{
	int i,tmp_min;
	tmp_min = data.stdoutdata[img->view_index][0].tr;
	*pos = 0;
	for ( i=1; i<data.buffer_num[img->view_index]; i++)
	{
		if (data.stdoutdata[img->view_index][i].tr<tmp_min)
		{
			tmp_min = data.stdoutdata[img->view_index][i].tr;
			*pos = i;
		}
	}
}
void delete_trbuffer( outdata *data, int pos)
{
	int i;
	for ( i=pos; i< data->buffer_num[img->view_index]-1; i++ )
	{
		data->stdoutdata[img->view_index][i] = data->stdoutdata[img->view_index][i+1];
	}
	data->buffer_num[img->view_index]--;
}

void addCurrMvtoBuf()
{
	int i, k, x, y;
	for ( i=0; i<REF_MAXBUFFER; i++ )
	{
		if ( img->coding_order == img->imgcoi_ref[i] )
		{
			break;
		}
	}
	if (curr_RPS.referd_by_others && img->type != INTRA_IMG)
	{
		for (k=0; k<2; k++)
		{
			for (y=0; y<img->height/MIN_BLOCK_SIZE; y++)
			{
				for (x=0; x<img->width/MIN_BLOCK_SIZE; x++)
				{
#if DHP
					mvbuf[i][y][x][k] = (((img->type==F_IMG)||(img->type==P_IMG)) ? img->tmp_mv:img->fw_mv)[y][x][k];
#else
					mvbuf[i][y][x][k] = (img->type==INTER_IMG ? img->tmp_mv:img->fw_mv)[y][x][k];
#endif
				}
			}
		}

	}

	for ( y = 0; y < img->height / MIN_BLOCK_SIZE; y++ )
	{
		for ( x = 0; x < img->width / MIN_BLOCK_SIZE ; x++ )
		{
#if DHP
			refbuf[i][y][x] = (((img->type==F_IMG)||(img->type==P_IMG)||(img->type==INTRA_IMG))? refFrArr:img->fw_refFrArr)[y][x];
#else
			refbuf[i][y][x] = (img->type==INTER_IMG? refFrArr:img->fw_refFrArr)[y][x];
#endif
		}
	}
}

void depth_frame_postprocessing (SNRParameters *snr )
{
	//pic dist by Grandview Semi. @ [06-07-20 15:25]
	img->PrevPicDistanceLsb = (img->coding_order%256);
	if ( p_ref && !input->ref_pic_order )
	{
#ifdef AVS2_S2_BGLONGTERM
		if(img->typeb == BACKGROUND_IMG && background_picture_output_flag==0)
			find_snr_background( snr, p_ref_background);
		else
#endif
			find_snr ( snr, p_ref ); // if ref sequence exist
	}
	{

		int pointer_tmp = outprint.depth_buffer_num[img->view_index];


		int i;


		outprint.depth_stdoutdata[img->view_index][pointer_tmp].type = img->type;
#ifdef AVS2_S2_BGLONGTERM
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].typeb = img->typeb;
#endif
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].framenum = img->tr;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].tr = img->tr;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].qp = img->qp;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].snr_y = snr->snr_y;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].snr_u = snr->snr_u;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].snr_v = snr->snr_v;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].tmp_time = tmp_time;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].picture_structure = img->picture_structure;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].curr_frame_bits = StatBitsPtr->curr_frame_bits;
		outprint.depth_stdoutdata[img->view_index][pointer_tmp].emulate_bits = StatBitsPtr->emulate_bits;
		outprint.depth_buffer_num[img->view_index]++;

		addCurrMvtoBuf();
#if MV_COMPRESSION
		if (curr_RPS.referd_by_others && img->type!=I_IMG )
			compressMotion();
#endif

#ifdef AVS2_S2_BGLONGTERM
		if(img->typeb == BACKGROUND_IMG && background_picture_output_flag==0)
		{
			write_GB_frame(p_out_background);
			report_frame( outprint, 0 );
			depth_delete_trbuffer( & outprint, 0 );
		}
		else
#endif

#if !REF_OUTPUT
			for ( i=0; i< outprint.depth_buffer_num[img->view_index]; i++)
			{
				depth_min_tr(outprint,&pos);
				if ( outprint.depth_stdoutdata[img->view_index][pos].tr < img->tr ||  outprint.depth_stdoutdata[img->view_index][pos].tr == (last_output+1) )
				{
					last_output = outprint.depth_stdoutdata[img->view_index][pos].tr;
					depth_report_frame( outprint, pos );
					write_frame( p_out, outprint.depth_stdoutdata[img->view_index][pos].tr );
					depth_delete_trbuffer( &outprint, pos );
					i--;
				}
				else
				{
					break;
				}
			}
#else 
			if (img->coding_order+total_frames*256>= picture_reorder_delay )
			{

				int tmp_min,pos=-1;
				tmp_min = 1<<20;

				for ( i=0; i<outprint.depth_buffer_num[img->view_index]; i++)
				{

					if (outprint.depth_stdoutdata[img->view_index][i].tr<tmp_min && outprint.depth_stdoutdata[img->view_index][i].tr>multiView_depth_last_output[img->view_index])

					{
						pos=i;
						tmp_min=outprint.depth_stdoutdata[img->view_index][i].tr;

					}
				}
				if (pos!=-1)
				{

					multiView_depth_last_output[img->view_index] = outprint.depth_stdoutdata[img->view_index][pos].tr;

					depth_report_frame( outprint, pos );
					write_frame( p_out, outprint.depth_stdoutdata[img->view_index][pos].tr );
					depth_delete_trbuffer( &outprint, pos );

				}

			}
#endif


	}

}


void depth_report_frame (outdata data, int pos)
{
	FILE *file;
	char *Frmfld;
	char Frm[] = "FRM";
	char Fld[] = "FLD";
	file = fopen ( "stat.dat", "at" );
	if (data.depth_stdoutdata[img->view_index][pos].picture_structure)
	{
		Frmfld = Frm;
	}
	else
	{
		Frmfld = Fld;
	}
#if INTERLACE_CODING  
	if (img->is_field_sequence)   //rcs??
	{
		Frmfld = Fld;
	}
#endif
	if ( data.depth_stdoutdata[img->view_index][pos].tr == end_SeqTr ) // I picture
	{
		//if ( img->new_sequence_flag == 1 )
		{
			img->sequence_end_flag = 0;
			fprintf ( stdout, "Sequence End\n\n" );
		}
	}
	if ( data.depth_stdoutdata[img->view_index][pos].tr == next_IDRtr )
	{
		if ( vec_flag )
		{
			vec_flag = 0;
			fprintf ( stdout, "Video Edit Code\n" );
		}
		fprintf ( stdout, "Sequence Header\n" );
	}

	if ( data.depth_stdoutdata[img->view_index][pos].type == I_IMG ) // I picture
	{
#ifdef AVS2_S2_BGLONGTERM
		if(data.depth_stdoutdata[img->view_index][pos].typeb == BACKGROUND_IMG && input->profile_id == 0x50)
		{
			if(background_picture_output_flag)
			{
				printf ( "%3d(G)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
					data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.depth_stdoutdata[img->view_index][pos].curr_frame_bits, data.depth_stdoutdata[img->view_index][pos].emulate_bits );

				fprintf ( file, "%3d(G)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
					data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
			}
			else
			{
				printf ( "%3d(GB) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
					data.stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.depth_stdoutdata[img->view_index][pos].curr_frame_bits, data.depth_stdoutdata[img->view_index][pos].emulate_bits );

				fprintf ( file, "%3d(GB) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
					data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
			}
		}
		else
		{
			printf ( "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
				data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.depth_stdoutdata[img->view_index][pos].curr_frame_bits, data.depth_stdoutdata[img->view_index][pos].emulate_bits );

			fprintf ( file, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
				data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
		}
#else
		printf ( "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.depth_stdoutdata[img->view_index][pos].framenum, data.depth_stdoutdata[img->view_index][pos].tr, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.depth_stdoutdata[img->view_index][pos].curr_frame_bits, data.depth_stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.depth_stdoutdata[img->view_index][pos].framenum, data.depth_stdoutdata[img->view_index][pos].tr, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
#endif
	}

#ifdef AVS2_S2_S
	else if ( data.depth_stdoutdata[img->view_index][pos].type == P_IMG && data.depth_stdoutdata[img->view_index][pos].typeb != BP_IMG)
#else
	else if ( data.depth_stdoutdata[img->view_index][pos].type ==P_IMG ) // P pictures
#endif
	{
		printf ( "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.depth_stdoutdata[img->view_index][pos].curr_frame_bits, data.depth_stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
	}
#ifdef AVS2_S2_S
	else if ( data.depth_stdoutdata[img->view_index][pos].type == P_IMG && data.depth_stdoutdata[img->view_index][pos].typeb == BP_IMG)
	{
		printf ( "%3d(S)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.depth_stdoutdata[img->view_index][pos].curr_frame_bits, data.depth_stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(S)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
	}
#endif
#if DHP
	else if ( data.depth_stdoutdata[img->view_index][pos].type ==F_IMG ) // F pictures
	{
		printf ( "%3d(F)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.depth_stdoutdata[img->view_index][pos].curr_frame_bits, data.depth_stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(F)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
	}
#endif 
	else // B pictures
	{
		printf ( "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\n",
			data.depth_stdoutdata[img->view_index][pos].framenum+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld, data.depth_stdoutdata[img->view_index][pos].curr_frame_bits, data.depth_stdoutdata[img->view_index][pos].emulate_bits );

		fprintf ( file, "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n",
			data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].tr+total_frames*256, data.depth_stdoutdata[img->view_index][pos].qp, data.depth_stdoutdata[img->view_index][pos].snr_y, data.depth_stdoutdata[img->view_index][pos].snr_u, data.depth_stdoutdata[img->view_index][pos].snr_v, data.depth_stdoutdata[img->view_index][pos].tmp_time, Frmfld ); //20080721
	}

	fclose ( file );
	fflush ( stdout );
	FrameNum++;

}

#endif